{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os \n",
    "import numpy as np \n",
    "from google.protobuf import text_format, json_format\n",
    "import re\n",
    "import json \n",
    "import sys \n",
    "import tqdm \n",
    "\n",
    "# add ./scripts path to sys path\n",
    "sys.path.append(\"..\") \n",
    "from src.utils import getMeshDimensions, getMeshCenter\n",
    "import trimesh "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "# collect all object ids \n",
    "google_scans_path = \"/media/junting/SSD_data/google_object_dataset\"\n",
    "object_ids = os.listdir(google_scans_path)\n",
    "exclude_ids = ['glb', 'google_scanned_objects.proto']\n",
    "object_ids = [object_id for object_id in object_ids if object_id not in exclude_ids]\n",
    "\n",
    "# output path\n",
    "output_path = \"../../data/google_scanned_object/\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Util functions "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "def parse_metadata(file):\n",
    "    # Create a proto object and serialize it to a text proto string.\n",
    "    metadata_proto = google_scanned_objects_pb2.Metadata()\n",
    "    # Parse a text proto into dictionary.\n",
    "    with open(file, 'r') as f:\n",
    "        message = text_format.Merge(f.read(), metadata_proto)\n",
    "        meta_dict = json_format.MessageToDict(message)\n",
    "    return meta_dict"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "def collect_thumbnails(objects_dir, target_dir, object_ids):\n",
    "    \"\"\"\n",
    "    Collect thumbnails for all objects\n",
    "    \"\"\"\n",
    "    thumbnails = {}\n",
    "    for object_id in tqdm.tqdm(object_ids):\n",
    "        thumbnail_dir = os.path.join(objects_dir, object_id, \"thumbnails\")\n",
    "        # copy the first thumbnail \"0.jpg\" to target_dir\n",
    "        thumbnail_path = os.path.join(thumbnail_dir, \"0.jpg\")\n",
    "        target_path = os.path.join(target_dir, object_id + \".jpg\")\n",
    "        os.system(\"cp {} {}\".format(thumbnail_path, target_path))\n",
    "        \n",
    "    return thumbnails"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Compile Google Scanned Objects protobuf message "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "# !protoc --proto_path=\"../data/google_scanned_object/\" --python_out=\"../protobuf\"  \"../data/google_scanned_object/google_scanned_objects.proto\" "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Load metadata from file"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "# import compiled protobuf message  \n",
    "sys.path.append(\"..\")\n",
    "import protobuf.google_scanned_objects_pb2 as google_scanned_objects_pb2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<module 'protobuf.google_scanned_objects_pb2' from '/home/junting/franka_ws/src/franka_fisher/instruct_to_policy/scripts/jupyter/../protobuf/google_scanned_objects_pb2.py'>\n"
     ]
    }
   ],
   "source": [
    "print(google_scanned_objects_pb2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "# collect metadata for the whole dataset \n",
    "metadata = {}\n",
    "\n",
    "for object_id in object_ids:\n",
    "    pbtxt_file_path = os.path.join(google_scans_path, object_id, \"metadata.pbtxt\")\n",
    "    metadata[object_id] = parse_metadata(pbtxt_file_path)\n",
    "    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "# # save metadata to json file\n",
    "# with open('google_scans_metadata.json', 'w') as f:\n",
    "#     json.dump(metadata, f)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "dict_keys(['11pro_SL_TRX_FG', '2_of_Jenga_Classic_Game', '30_CONSTRUCTION_SET', '3D_Dollhouse_Happy_Brother', '3D_Dollhouse_Lamp', '3D_Dollhouse_Refrigerator', '3D_Dollhouse_Sink', '3D_Dollhouse_Sofa', '3D_Dollhouse_Swing', '3D_Dollhouse_TablePurple', '3M_Antislip_Surfacing_Light_Duty_White', '3M_Vinyl_Tape_Green_1_x_36_yd', '45oz_RAMEKIN_ASST_DEEP_COLORS', '50_BLOCKS', '5_HTP', '60_CONSTRUCTION_SET', 'ACE_Coffee_Mug_Kristen_16_oz_cup', 'adistar_boost_m', 'adizero_5Tool_25', 'adizero_F50_TRX_FG_LEA', 'adiZero_Slide_2_SC', 'Adrenaline_GTS_13_Color_DrkDenimWhtBachlorBttnSlvr_Size_50_yfK40TNjq0V', 'Adrenaline_GTS_13_Color_WhtObsdianBlckOlmpcSlvr_Size_70', 'Top_Paw_Dog_Bow_Bone_Ceramic_13_fl_oz_total', 'TOP_TEN_HI', 'TOP_TEN_HI_60KlbRbdoJA', 'Tory_Burch_Kaitlin_Ballet_Mestico_in_BlackGold', 'Tory_Burch_Kiernan_Riding_Boot', 'Tory_Burch_Reva_Metal_Logo_Litus_Snake_Print_in_dark_BranchGold', 'Tory_Burch_Sabe_65mm_Bootie_Split_Suede_in_Caramel', 'TOWER_TUMBLING', 'Toysmith_Windem_Up_Flippin_Animals_Dog', 'Toys_R_Us_Treat_Dispenser_Smart_Puzzle_Foobler', 'Transformers_Age_of_Extinction_Mega_1Step_Bumblebee_Figure', 'Transformers_Age_of_Extinction_Stomp_and_Chomp_Grimlock_Figure', 'Travel_Mate_P_series_Notebook', 'Travel_Smart_Neck_Rest_Inflatable', 'TriStar_Products_PPC_Power_Pressure_Cooker_XL_in_Black', 'TROCHILUS_BOOST', 'Tune_Belt_Sport_Armband_For_Samsung_Galaxy_S3', 'TURBOPROP_AIRPLANE_WITH_PILOT', 'Twinlab_100_Whey_Protein_Fuel_Chocolate', 'Twinlab_100_Whey_Protein_Fuel_Cookies_and_Cream', 'Threshold_Dinner_Plate_Square_Rim_White_Porcelain', 'Threshold_Hand_Towel_Blue_Medallion_16_x_27', 'Threshold_Performance_Bath_Sheet_Sandoval_Blue_33_x_63', 'Threshold_Porcelain_Coffee_Mug_All_Over_Bead_White', 'Threshold_Porcelain_Pitcher_White', 'Threshold_Porcelain_Serving_Bowl_Coupe_White', 'Threshold_Porcelain_Spoon_Rest_White', 'Threshold_Porcelain_Teapot_White', 'Threshold_Ramekin_White_Porcelain', 'Threshold_Salad_Plate_Square_Rim_Porcelain', 'Threshold_Textured_Damask_Bath_Towel_Pink', 'Air_Hogs_Wind_Flyers_Set_Airplane_Red', 'ASICS_GEL1140V_WhiteBlackSilver', 'Asus_X99Deluxe_Motherboard_ATX_LGA2011v3_Socket', 'BIA_Porcelain_Ramekin_With_Glazed_Rim_35_45_oz_cup', 'Breyer_Horse_Of_The_Year_2015', 'Canon_Pixma_Chromalife_100_Magenta_8', 'CHICKEN_NESTING', 'Cole_Hardware_Electric_Pot_Assortment_55', 'CoQ10_BjTLbuRVt1t', 'Crazy_8', 'Deskstar_Desk_Top_Hard_Drive_1_TB', 'DPC_Handmade_Hat_Brown', 'Ecoforms_Plant_Container_GP16A_Coral', 'Ecoforms_Plant_Container_URN_NAT', 'Ecoforms_Quadra_Saucer_SQ1_Avocado', 'FARM_ANIMAL', 'FRACTION_FUN_n4h4qte23QR', 'Gigabyte_GA78LMTUSB3_50_Motherboard_Micro_ATX_Socket_AM3', 'Great_Jones_Wingtip', 'Home_Fashions_Washcloth_Linen', 'JA_Henckels_International_Premio_Cutlery_Block_Set_14Piece', 'Lalaloopsy_Peanut_Big_Top_Tricycle', 'Superman_Battle_of_Smallville', 'Supernatural_Ouija_Board_Game', 'SUPERSTAR_CLR', 'Super_Mario_3D_World_Deluxe_Set', 'Super_Mario_3D_World_Deluxe_Set_yThuvW9vZed', 'Super_Mario_3D_World_Wii_U_Game', 'Super_Mario_Kart_Super_Nintendo_Entertainment_System', 'Sushi_Mat', 'Swiss_Miss_Hot_Cocoa_KCups_Milk_Chocolate_12_count', 'TABLEWARE_SET', 'TABLEWARE_SET_5CHkPjjxVpp', 'TABLEWARE_SET_5ww1UFLuCJG', 'Tag_Dishtowel_18_x_26', 'Tag_Dishtowel_Basket_Weave_Red_18_x_26', 'Tag_Dishtowel_Dobby_Stripe_Blue_18_x_26', 'Tag_Dishtowel_Green', 'Tag_Dishtowel_Waffle_Gray_Checks_18_x_26', 'Target_Basket_Medium', 'TEA_SET', 'Teenage_Mutant_Ninja_Turtles_Rahzar_Action_Figure', 'Tena_Pads_Heavy_Long_42_pads', 'Shaxon_100_Molded_Category_6_RJ45RJ45_Shielded_Patch_Cord_White', 'Shurtape_30_Day_Removal_UV_Delct_15', 'Shurtape_Gaffers_Tape_Silver_2_x_60_yd', 'Shurtape_Tape_Purple_CP28', 'Sienna_Brown_Croc_Tieks_Patent_Leather_Crocodile_Print_Ballet_Flats', 'Simon_Swipe_Game', 'SIT_N_WALK_PUPPY', 'SLACK_CRUISER', 'Sleep_Optimizer', 'Smith_Hawken_Woven_BasketTray_Organizer_with_3_Compartments_95_x_9_x_13', 'Snack_Catcher_Snack_Dispenser', 'SNAIL_MEASURING_TAPE', 'Sonicare_2_Series_Toothbrush_Plaque_Control', 'Sonny_School_Bus', 'Sony_Acid_Music_Studio', 'Santa_Cruz_Mens', 'Santa_Cruz_Mens_G7kQXK7cIky', 'Santa_Cruz_Mens_umxTczr1Ygg', 'Santa_Cruz_Mens_vnbiTDDt5xH', 'Santa_Cruz_Mens_YmsMDkFf11Z', 'Sapota_Threshold_4_Ceramic_Round_Planter_Red', 'SAPPHIRE_R7_260X_OC', 'Schleich_African_Black_Rhino', 'Schleich_Allosaurus', 'Schleich_Bald_Eagle', 'Schleich_Hereford_Bull', 'Schleich_Lion_Action_Figure', 'Schleich_Spinosaurus_Action_Figure', 'Schleich_S_Bayala_Unicorn_70432', 'Schleich_Therizinosaurus_ln9cruulPqc', 'SCHOOL_BUS', 'Seagate_1TB_Backup_Plus_portable_drive_Blue', 'Seagate_1TB_Backup_Plus_portable_drive_for_Mac', 'Seagate_1TB_Backup_Plus_portable_drive_Silver', 'Seagate_1TB_Wireless_Plus_mobile_device_storage', 'Seagate_3TB_Central_shared_storage', 'Seagate_Archive_HDD_8_TB_Internal_hard_drive_SATA_6Gbs_35_ST8000AS0002', 'Sea_to_Summit_Xl_Bowl', 'SHAPE_MATCHING', 'SHAPE_MATCHING_NxacpAY9jDt', 'SHAPE_SORTER', 'Retail_Leadership_Summit_eCT3zqHYIkX', 'Retail_Leadership_Summit_tQFCizMt6g0', 'Rexy_Glove_Heavy_Duty_Gloves_Medium', 'Rexy_Glove_Heavy_Duty_Large', 'RJ_Rabbit_Easter_Basket_Blue', 'ROAD_CONSTRUCTION_SET', 'Romantic_Blush_Tieks_Metallic_Italian_Leather_Ballet_Flats', 'Room_Essentials_Bowl_Turquiose', 'Room_Essentials_Dish_Drainer_Collapsible_White', 'Room_Essentials_Fabric_Cube_Lavender', 'Room_Essentials_Kitchen_Towels_16_x_26_2_count', 'Room_Essentials_Mug_White_Yellow', 'Room_Essentials_Salad_Plate_Turquoise', 'Rose_Garden_Tieks_Leather_Ballet_Flats_with_Floral_Rosettes', 'Rubbermaid_Large_Drainer', 'Saccharomyces_Boulardii_MOS_Value_Size', 'SAMBA_HEMP', 'SAMe_200', 'SAMe_200_KX7ZmOw47co', 'SAMOA', 'Samoa_onepiece', 'Samsung_CLTC406S_Toner_Cartridge_Cyan_1pack', 'Razer_BlackWidow_Stealth_2014_Keyboard_07VFzIVabgh', 'Razer_Blackwidow_Tournament_Edition_Keyboard', 'Razer_BlackWidow_Ultimate_2014_Mechanical_Gaming_Keyboard', 'Razer_Goliathus_Control_Edition_Small_Soft_Gaming_Mouse_Mat', 'Razer_Kraken_71_Chroma_headset_Full_size_Black', 'Razer_Kraken_Pro_headset_Full_size_Black', 'Razer_Naga_MMO_Gaming_Mouse', 'Razer_Taipan_Black_Ambidextrous_Gaming_Mouse', 'Razer_Taipan_White_Ambidextrous_Gaming_Mouse', 'ReadytoUse_Rolled_Fondant_Pure_White_24_oz_box', 'Real_Deal_1nIwCHX1MTh', 'RedBlack_Nintendo_3DSXL', 'Reebok_ALLYLYNN', 'Reebok_BREAKPOINT_LO_2V', 'Reebok_BREAKPOINT_MID', 'Reebok_CLASSIC_JOGGER', 'Reebok_CLASSIC_LEGACY_II', 'Reebok_CL_DIBELLO_II', 'Reebok_CL_LTHR_R12', 'Reebok_CL_RAYEN', 'Reebok_COMFORT_REEFRESH_FLIP', 'Reebok_DMX_MAX_MANIA_WD_D', 'Reebok_DMX_MAX_PLUS_ATHLETIC', 'Reebok_DMX_MAX_PLUS_RAINWALKER', 'Reebok_EASYTONE_CL_LEATHER', 'Reebok_FS_HI_INT_R12', 'Reebok_FS_HI_MINI', 'Perricone_MD_The_Crease_Cure_Duo', 'Perricone_MD_The_Metabolic_Formula_Supplements', 'Perricone_MD_The_Power_Treatments', 'Perricone_MD_Vitamin_C_Ester_15', 'Perricone_MD_Vitamin_C_Ester_Serum', 'Persona_Q_Shadow_of_the_Labyrinth_Nintendo_3DS', 'PETS_ACCESSORIES', 'Pet_Dophilus_powder', 'PHEEHAN_RUN', 'Philips_60ct_Warm_White_LED_Smooth_Mini_String_Lights', 'Philips_EcoVantage_43_W_Light_Bulbs_Natural_Light_2_pack', 'Philips_Sonicare_Tooth_Brush_2_count', 'Phillips_Caplets_Size_24', 'Phillips_Colon_Health_Probiotic_Capsule', 'Phillips_Milk_of_Magnesia_Saline_Laxative_Liquid_Original', 'Perricone_MD_No_Bronzer_Bronzer', 'Perricone_MD_No_Foundation_Foundation_No_1', 'Perricone_MD_No_Foundation_Serum', 'Perricone_MD_No_Lipstick_Lipstick', 'Perricone_MD_No_Mascara_Mascara', 'Perricone_MD_Nutritive_Cleanser', 'Perricone_MD_Omega_3_Supplements', 'Perricone_MD_OVM', 'Perricone_MD_Photo_Plasma', 'Perricone_MD_Skin_Clear_Supplements', 'Perricone_MD_Skin_Total_Body_Supplements', 'Perricone_MD_Super_Berry_Powder_with_Acai_Supplements', 'Perricone_MD_Blue_Plasma_Orbital', 'Perricone_MD_Chia_Serum', 'Perricone_MD_Cold_Plasma', 'Perricone_MD_Cold_Plasma_Body', 'Perricone_MD_Face_Finishing_Moisturizer', 'Perricone_MD_Face_Finishing_Moisturizer_4_oz', 'Perricone_MD_Firming_Neck_Therapy_Treatment', 'Perricone_MD_Health_Weight_Management_Supplements', 'Perricone_MD_High_Potency_Evening_Repair', 'Perricone_MD_Hypoallergenic_Firming_Eye_Cream_05_oz', 'Perricone_MD_Hypoallergenic_Gentle_Cleanser', 'Perricone_MD_Neuropeptide_Facial_Conformer', 'OXO_Soft_Works_Can_Opener_SnapLock', 'Paint_Maker', 'Paper_Mario_Sticker_Star_Nintendo_3DS_Game', 'PARENT_ROOM_FURNITURE_SET_1', 'PARENT_ROOM_FURNITURE_SET_1_DLKEy8H4mwK', 'Pass_The_Popcorn_Movie_Guessing_Game', 'Paul_Frank_Dot_Lunch_Box', 'PEEKABOO_ROLLER', 'Pennington_Electric_Pot_Cabana_4', 'Pepsi_Caffeine_Free_Diet_12_CT', 'Pepsi_Cola_Caffeine_Free_12_12_fl_oz_355_ml_cans_144_fl_oz_426_lt', 'Pepsi_Cola_Wild_Cherry_Diet_12_12_fl_oz_355_ml_cans_144_fl_oz_426_lt', 'Pepsi_Max_Cola_Zero_Calorie_12_12_fl_oz_355_ml_cans_144_fl_oz_426_lt', 'PEPSI_NEXT_CACRV', 'Perricoen_MD_No_Concealer_Concealer', 'Perricone_MD_AcylGlutathione_Deep_Crease_Serum', 'Perricone_MD_AcylGlutathione_Eye_Lid_Serum', 'MARTIN_WEDGE_LACE_BOOT', 'Marvel_Avengers_Titan_Hero_Series_Doctor_Doom', 'Mastic_Gum', 'Mattel_SKIP_BO_Card_Game', 'Matte_Black_Tieks_Italian_Leather_Ballet_Flats', 'MEAT_SET', 'Melissa_Doug_Cart_Turtle_Block', 'Melissa_Doug_Chunky_Puzzle_Vehicles', 'Melissa_Doug_Felt_Food_Pizza_Set', 'Melissa_Doug_Jumbo_Knob_Puzzles_Barnyard_Animals', 'Melissa_Doug_Pattern_Blocks_and_Boards', 'Melissa_Doug_Pound_and_Roll', 'Melissa_Doug_See_Spell', 'Melissa_Doug_Shape_Sorting_Clock', 'Melissa_Doug_Traffic_Signs_and_Vehicles', 'Mens_ASV_Billfish_Boat_Shoe_in_Dark_Brown_Leather_zdHVHXueI3w', 'Mens_ASV_Billfish_Boat_Shoe_in_Tan_Leather_wmUJ5PbwANc', 'Mens_ASV_Shock_Light_Bungee_in_Light_Grey_xGCOvtLDnQJ', 'Mens_Authentic_Original_Boat_Shoe_in_Navy_Leather_NHHQddDLQys', 'Mens_Authentic_Original_Boat_Shoe_in_Navy_Leather_RpT4GvUXRRP', 'Mens_Authentic_Original_Boat_Shoe_in_Navy_Leather_xgoEcZtRNmH', 'Mens_Bahama_in_Black_b4ADzYywRHl', 'Mens_Bahama_in_Khaki_Oyster_xU2jeqYwhQJ', 'Home_Fashions_Washcloth_Olive_Green', 'Horses_in_Pink_Pencil_Case', 'Horse_Dreams_Pencil_Case', 'House_of_Cards_The_Complete_First_Season_4_Discs_DVD', 'HP_1800_Tablet_8GB_7', 'HP_Card_Invitation_Kit', 'Hyaluronic_Acid', 'HyperX_Cloud_II_Headset_Gun_Metal', 'HyperX_Cloud_II_Headset_Red', 'Imaginext_Castle_Ogre', 'Inositol', 'InterDesign_Over_Door', 'INTERNATIONAL_PAPER_Willamette_4_Brown_Bag_500Count', 'In_Green_Company_Surface_Saver_Ring_10_Terra_Cotta', 'IsoRich_Soy', 'Jansport_School_Backpack_Blue_Streak', 'JarroDophilusFOS_Value_Size', 'JarroSil_Activated_Silicon', 'JarroSil_Activated_Silicon_5exdZHIeLAp', 'Jarrow_Formulas_Glucosamine_Hci_Mega_1000_100_ct', 'Jarrow_Glucosamine_Chondroitin_Combination_120_Caps', 'Jawbone_UP24_Wireless_Activity_Tracker_Pink_Coral_L', 'Gigabyte_GA970AUD3P_10_Motherboard_ATX_Socket_AM3', 'Gigabyte_GAZ97XSLI_10_motherboard_ATX_LGA1150_Socket_Z97', 'GIRLS_DECKHAND', 'Glycerin_11_Color_AqrsDrsdnBluBlkSlvShckOrng_Size_50', 'Glycerin_11_Color_BrllntBluSkydvrSlvrBlckWht_Size_80', 'Google_Cardboard_Original_package', 'GoPro_HERO3_Composite_Cable', 'GRANDFATHER_DOLL', 'GRANDMOTHER', 'Grand_Prix', 'Granimals_20_Wooden_ABC_Blocks_Wagon', 'Granimals_20_Wooden_ABC_Blocks_Wagon_85VdSftGsLi', 'Granimals_20_Wooden_ABC_Blocks_Wagon_g2TinmUGGHI', 'Great_Dinos_Triceratops_Toy', 'Ecoforms_Saucer_SQ3_Turquoise', 'Elephant', 'Embark_Lunch_Cooler_Blue', 'ENFR_MID_ENFORCER', 'Envision_Home_Dish_Drying_Mat_Red_6_x_18', 'Epson_273XL_Ink_Cartridge_Magenta', 'Epson_DURABrite_Ultra_786_Black_Ink_Cartridge_T786120S', 'Epson_Ink_Cartridge_126_Yellow', 'Epson_Ink_Cartridge_Black_200', 'Epson_LabelWorks_LC4WBN9_Tape_reel_labels_047_x_295_Roll_Black_on_White', 'Epson_LabelWorks_LC5WBN9_Tape_reel_labels_071_x_295_Roll_Black_on_White', 'Epson_T5803_Ink_Cartridge_Magenta_1pack', 'Epson_UltraChrome_T0543_Ink_Cartridge_Magenta_1pack', 'Epson_UltraChrome_T0548_Ink_Cartridge_Matte_Black_1pack', 'F10_TRX_FG_ssscuo9tGxb', 'F10_TRX_TF_rH7tmKCdUJq', 'F5_TRX_FG', 'FAIRY_TALE_BLOCKS', 'Ecoforms_Plant_Container_URN_SAN', 'Ecoforms_Plant_Plate_S11Turquoise', 'Ecoforms_Plant_Pot_GP9AAvocado', 'Ecoforms_Plant_Pot_GP9_SAND', 'Ecoforms_Plant_Saucer_S14MOCHA', 'Ecoforms_Plant_Saucer_S14NATURAL', 'Ecoforms_Plant_Saucer_S17MOCHA', 'Ecoforms_Plant_Saucer_S20MOCHA', 'Ecoforms_Plant_Saucer_SQ1HARVEST', 'Ecoforms_Plant_Saucer_SQ8COR', 'Ecoforms_Plate_S20Avocado', 'Ecoforms_Pot_Nova_6_Turquoise', 'Ecoforms_Plant_Container_QP6CORAL', 'Ecoforms_Plant_Container_QP6HARVEST', 'Ecoforms_Plant_Container_QP_Harvest', 'Ecoforms_Plant_Container_QP_Turquoise', 'Ecoforms_Plant_Container_Quadra_Sand_QP6', 'Ecoforms_Plant_Container_Quadra_Turquoise_QP12', 'Ecoforms_Plant_Container_S14Turquoise', 'Ecoforms_Plant_Container_S24NATURAL', 'Ecoforms_Plant_Container_S24Turquoise', 'Ecoforms_Plant_Container_SB9Turquoise', 'Ecoforms_Plant_Container_Urn_55_Avocado', 'Ecoforms_Plant_Container_Urn_55_Mocha', 'Diamond_Visions_Scissors_Red', 'Diet_Pepsi_Soda_Cola12_Pack_12_oz_Cans', 'Digital_Camo_Double_Decker_Lunch_Bag', 'DIM_CDG', 'DINING_ROOM_CLASSIC', 'DINING_ROOM_CLASSIC_UJuxQ0hv5XU', 'DINNING_ROOM_FURNITURE_SET_1', 'Dino_3', 'Dino_4', 'Dino_5', 'Dixie_10_ounce_Bowls_35_ct', 'Dog', 'DOLL_FAMILY', 'Don_Franciscos_Gourmet_Coffee_Medium_Decaf_100_Colombian_12_oz_340_g', 'Down_To_Earth_Ceramic_Orchid_Pot_Asst_Blue', 'Down_To_Earth_Orchid_Pot_Ceramic_Lime', 'Down_To_Earth_Orchid_Pot_Ceramic_Red', 'Cole_Hardware_Electric_Pot_Cabana_55', 'Cole_Hardware_Flower_Pot_1025', 'Cole_Hardware_Hammer_Black', 'Cole_Hardware_Mini_Honey_Dipper', 'Cole_Hardware_Mug_Classic_Blue', 'Cole_Hardware_Orchid_Pot_85', 'Cole_Hardware_Plant_Saucer_Brown_125', 'Cole_Hardware_Plant_Saucer_Glazed_9', 'Cole_Hardware_Saucer_Electric', 'Cole_Hardware_Saucer_Glazed_6', 'Cole_Hardware_School_Bell_Solid_Brass_38', 'Colton_Wntr_Chukka_y4jO0I8JQFW', 'CONE_SORTING', 'CONE_SORTING_kg5fbARBwts', 'Connect_4_Launchers', 'Cootie_Game', 'Cootie_Game_tDhURNbfU5J', 'Copperhead_Snake_Tieks_Brown_Snake_Print_Ballet_Flats', 'CoQ10', 'CHICKEN_RACER', 'CHILDRENS_ROOM_NEO', 'CHILDREN_BEDROOM_CLASSIC', 'Circo_Fish_Toothbrush_Holder_14995988', 'CITY_TAXI_POLICE_CAR', 'ClimaCool_Aerate_2_W_Wide', 'CLIMACOOL_BOAT_BREEZE_IE6CyqSaDwN', 'Clorox_Premium_Choice_Gloves_SM_1_pair', 'Closetmaid_Premium_Fabric_Cube_Red', 'Clue_Board_Game_Classic_Edition', 'COAST_GUARD_BOAT', 'Cole_Hardware_Antislip_Surfacing_Material_White', 'Cole_Hardware_Antislip_Surfacing_White_2_x_60', 'Cole_Hardware_Bowl_Scirocco_YellowBlue', 'Cole_Hardware_Butter_Dish_Square_Red', 'Cole_Hardware_Deep_Bowl_Good_Earth_1075', 'Cole_Hardware_Dishtowel_Blue', 'Cole_Hardware_Dishtowel_BlueWhite', 'Cole_Hardware_Dishtowel_Multicolors', 'Cole_Hardware_Dishtowel_Red', 'Cole_Hardware_Dishtowel_Stripe', 'Bifidus_Balance_FOS', 'Big_Dot_Aqua_Pencil_Case', 'Big_Dot_Pink_Pencil_Case', 'Big_O_Sponges_Assorted_Cellulose_12_pack', 'BIRD_RATTLE', 'BlackBlack_Nintendo_3DSXL', 'Blackcurrant_Lutein', 'Black_and_Decker_PBJ2000_FusionBlade_Blender_Jars', 'Black_and_Decker_TR3500SD_2Slice_Toaster', 'Black_Decker_CM2035B_12Cup_Thermal_Coffeemaker', 'Black_Decker_Stainless_Steel_Toaster_4_Slice', 'Black_Elderberry_Syrup_54_oz_Gaia_Herbs', 'Black_Forest_Fruit_Snacks_28_Pack_Grape', 'Black_Forest_Fruit_Snacks_Juicy_Filled_Centers_10_pouches_9_oz_total', 'BlueBlack_Nintendo_3DSXL', 'Blue_Jasmine_Includes_Digital_Copy_UltraViolet_DVD', 'Borage_GLA240Gamma_Tocopherol', 'Bradshaw_International_11642_7_Qt_MP_Plastic_Bowl', 'BRAILLE_ALPHABET_AZ', 'BREAKFAST_MENU', 'WATER_LANDING_NET', 'Weisshai_Great_White_Shark', 'Weston_No_22_Cajun_Jerky_Tonic_12_fl_oz_nLj64ZnGwDh', 'Weston_No_33_Signature_Sausage_Tonic_12_fl_oz', 'WHALE_WHISTLE_6PCS_SET', 'Whey_Protein_3_Flavor_Variety_Pack_12_Packets', 'Whey_Protein_Chocolate_12_Packets', 'Whey_Protein_Vanilla', 'Whey_Protein_Vanilla_12_Packets', 'White_Rose_Tieks_Leather_Ballet_Flats_with_Floral_Rosettes', 'Wild_Copper_Tieks_Metallic_Italian_Leather_Ballet_Flats', 'Wilton_Easy_Layers_Cake_Pan_Set', 'Wilton_Pearlized_Sugar_Sprinkles_525_oz_Gold', 'Wilton_PreCut_Parchment_Sheets_10_x_15_24_sheets', 'Winning_Moves_1180_Aggravation_Board_Game', 'Wishbone_Pencil_Case', 'Womens_Angelfish_Boat_Shoe_in_Linen_Leopard_Sequin_NJDwosWNeZz', 'Womens_Angelfish_Boat_Shoe_in_Linen_Oat', 'Womens_Cloud_Logo_Authentic_Original_Boat_Shoe_in_Black_Supersoft_cZR022qFI4k', 'Womens_Hikerfish_Boot_in_Black_Leopard_bVSNY1Le1sm', 'Womens_Hikerfish_Boot_in_Black_Leopard_ridcCWsv8rW', 'Womens_Hikerfish_Boot_in_Linen_Leather_Sparkle_Suede_imlP8VkwqIH', 'Womens_Hikerfish_Boot_in_Linen_Leather_Sparkle_Suede_QktIyAkonrU', 'Womens_Multi_13', 'Womens_Sequin_Bahama_in_White_Sequin_V9K1hf24Oxe', 'Womens_Sequin_Bahama_in_White_Sequin_XoR8xTlxj1g', 'Womens_Sequin_Bahama_in_White_Sequin_yGVsSA4tOwJ', 'Womens_Sparkle_Suede_Angelfish_in_Grey_Sparkle_Suede_Silver', 'Womens_Sparkle_Suede_Bahama_in_Silver_Sparkle_Suede_Grey_Patent_tYrIBLMhSTN', 'Womens_Sparkle_Suede_Bahama_in_Silver_Sparkle_Suede_Grey_Patent_x9rclU7EJXx', 'Womens_Suede_Bahama_in_Graphite_Suede_cUAjIMhWSO9', 'AllergenFree_JarroDophilus', 'ALPHABET_AZ_GRADIENT', 'ALPHABET_AZ_GRADIENT_WQb1ufEycSj', 'AMBERLIGHT_UP_W', 'Android_Figure_Chrome', 'Android_Figure_Orange', 'Android_Figure_Panda', 'Android_Lego', 'Animal_Crossing_New_Leaf_Nintendo_3DS_Game', 'Animal_Planet_Foam_2Headed_Dragon', 'Apples_to_Apples_Kids_Edition', 'Arm_Hammer_Diaper_Pail_Refills_12_Pack_MFWkmoweejt', 'Aroma_Stainless_Steel_Milk_Frother_2_Cup', 'Perricone_MD_Neuropeptide_Firming_Moisturizer', 'Perricone_MD_The_Cold_Plasma_Face_Eyes_Duo', 'Phillips_Stool_Softener_Liquid_Gels_30_liquid_gels', 'Poppin_File_Sorter_Blue', 'Razer_Abyssus_Ambidextrous_Gaming_Mouse', 'Reebok_FUELTRAIN', 'Reebok_SH_PRIME_COURT_MID', 'Retail_Leadership_Summit', 'SANDWICH_MEAL', 'Shark', 'Sony_Downloadable_Loops', 'Sterilite_Caddy_Blue_Sky_17_58_x_12_58_x_9_14', 'TERREX_FAST_R', 'Threshold_Bistro_Ceramic_Dinner_Plate_Ruby_Ring', 'Threshold_Tray_Rectangle_Porcelain', 'Top_Paw_Dog_Bowl_Blue_Paw_Bone_Ceramic_25_fl_oz_total', 'Twinlab_100_Whey_Protein_Fuel_Vanilla', 'UGG_Jena_Womens_Java_7', 'Vtech_Stack_Sing_Rings_636_Months', 'Womens_Audrey_Slip_On_Boat_Shoe_in_Graphite_Nubuck_xWVkCJ5vxZe', 'Womens_Bluefish_2Eye_Boat_Shoe_in_Linen_Natural_Sparkle_Suede_kqi81aojcOR', 'Womens_Cloud_Logo_Authentic_Original_Boat_Shoe_in_Black_Supersoft_8LigQYwf4gr', 'Womens_Suede_Bahama_in_Graphite_Suede_p1KUwoWbw7R', 'Womens_Bluefish_2Eye_Boat_Shoe_in_Linen_Natural_Sparkle_Suede_w34KNQ41csH', 'Womens_Bluefish_2Eye_Boat_Shoe_in_Linen_Oat', 'Womens_Bluefish_2Eye_Boat_Shoe_in_Linen_Oat_IbrSyJdpT3h', 'Womens_Bluefish_2Eye_Boat_Shoe_in_Linen_Oat_niKJKeWsmxY', 'Womens_Bluefish_2Eye_Boat_Shoe_in_Tan', 'Womens_Bluefish_2Eye_Boat_Shoe_in_White_Tumbled_YG44xIePRHw', 'Womens_Canvas_Bahama_in_Black', 'Womens_Canvas_Bahama_in_Black_vnJULsDVyq5', 'Womens_Canvas_Bahama_in_White_4UyOhP6rYGO', 'Womens_Canvas_Bahama_in_White_UfZPHGQpvz0', 'Womens_Suede_Bahama_in_Graphite_Suede_t22AJSRjBOX', 'Womens_Teva_Capistrano_Bootie', 'Womens_Teva_Capistrano_Bootie_ldjRT9yZ5Ht', 'Wooden_ABC_123_Blocks_50_pack', 'Wrigley_Orbit_Mint_Variety_18_Count', 'W_Lou_z0dkC78niiZ', 'Xyli_Pure_Xylitol', 'YumYum_D3_Liquid', 'ZigKick_Hoops', 'ZX700_lYiwcTIekXk', 'ZX700_mf9Pc06uL06', 'ZX700_mzGbdP3u6JB', 'Ultra_JarroDophilus', 'Unmellow_Yellow_Tieks_Neon_Patent_Leather_Ballet_Flats', 'US_Army_Stash_Lunch_Bag', 'Utana_5_Porcelain_Ramekin_Large', 'U_By_Kotex_Cleanwear_Heavy_Flow_Pads_32_Ct', 'U_By_Kotex_Sleek_Regular_Unscented_Tampons_36_Ct_Box', 'Vans_Cereal_Honey_Nut_Crunch_11_oz_box', 'VANS_FIRE_ROASTED_VEGGIE_CRACKERS_GLUTEN_FREE', 'VEGETABLE_GARDEN', 'Victor_Reversible_Bookend', 'Vtech_Cruise_Learn_Car_25_Years', 'Vtech_Roll_Learn_Turtle', 'Womens_Authentic_Original_Boat_Shoe_in_Classic_Brown_Leather', 'Womens_Authentic_Original_Boat_Shoe_in_Classic_Brown_Leather_48Nh7VuMwW6', 'Womens_Authentic_Original_Boat_Shoe_in_Classic_Brown_Leather_cJSCWiH7QmB', 'Womens_Authentic_Original_Boat_Shoe_in_Navy_Deerskin_50lWJaLWG8R', 'Womens_Betty_Chukka_Boot_in_Grey_Jersey_Sequin', 'Womens_Betty_Chukka_Boot_in_Navy_aEE8OqvMII4', 'Womens_Betty_Chukka_Boot_in_Navy_Jersey_Sequin_y0SsHk7dKUX', 'Womens_Betty_Chukka_Boot_in_Salt_Washed_Red_AL2YrOt9CRy', 'Womens_Bluefish_2Eye_Boat_Shoe_in_Brown_Deerskin_i1TgjjO0AKY', 'Womens_Bluefish_2Eye_Boat_Shoe_in_Brown_Deerskin_JJ2pfEHTZG7', 'Twinlab_Nitric_Fuel', 'Twinlab_Premium_Creatine_Fuel_Powder', 'TWISTED_PUZZLE', 'TWISTED_PUZZLE_twb4AyFtu8Q', 'TWIST_SHAPE', 'TZX_Runner', 'Ubisoft_RockSmith_Real_Tone_Cable_Xbox_360', 'UGG_Bailey_Bow_Womens_Clogs_Black_7', 'UGG_Bailey_Button_Triplet_Womens_Boots_Black_7', 'UGG_Bailey_Button_Womens_Boots_Black_7', 'UGG_Cambridge_Womens_Black_7', 'UGG_Classic_Tall_Womens_Boots_Chestnut_7', 'UGG_Classic_Tall_Womens_Boots_Grey_7', 'Tieks_Ballet_Flats_Diamond_White_Croc', 'Tieks_Ballet_Flats_Electric_Snake', 'Tiek_Blue_Patent_Tieks_Italian_Leather_Ballet_Flats', 'Timberland_Mens_Classic_2Eye_Boat_Shoe', 'Timberland_Mens_Earthkeepers_Casco_Bay_Canvas_Oxford', 'Timberland_Mens_Earthkeepers_Casco_Bay_Canvas_SlipOn', 'Timberland_Mens_Earthkeepers_Casco_Bay_Suede_1Eye', 'Timberland_Mens_Earthkeepers_Heritage_2Eye_Boat_Shoe', 'Timberland_Mens_Earthkeepers_Newmarket_6Inch_Cupsole_Boot', 'Timberland_Mens_Earthkeepers_Stormbuck_Chukka', 'Timberland_Mens_Earthkeepers_Stormbuck_Lite_Plain_Toe_Oxford', 'Timberland_Mens_Earthkeepers_Stormbuck_Plain_Toe_Oxford', 'Timberland_Womens_Classic_Amherst_2Eye_Boat_Shoe', 'Timberland_Womens_Earthkeepers_Classic_Unlined_Boat_Shoe', 'Timberland_Womens_Waterproof_Nellie_Chukka_Double', 'TOOL_BELT', 'TERREX_FAST_X_GTX', 'Tetris_Link_Game', 'Theanine', 'The_Coffee_Bean_Tea_Leaf_KCup_Packs_Jasmine_Green_Tea_16_count', 'The_Scooper_Hooper', 'Thomas_Friends_Woodan_Railway_Henry', 'Thomas_Friends_Wooden_Railway_Ascending_Track_Riser_Pack', 'Thomas_Friends_Wooden_Railway_Deluxe_Track_Accessory_Pack', 'Thomas_Friends_Wooden_Railway_Porter_5JzRhMm3a9o', 'Thomas_Friends_Wooden_Railway_Talking_Thomas_z7yi7UFHJRj', 'Threshold_Bamboo_Ceramic_Soap_Dish', 'Threshold_Basket_Natural_Finish_Fabric_Liner_Small', 'Threshold_Bead_Cereal_Bowl_White', 'Sootheze_Cold_Therapy_Elephant', 'Sootheze_Toasty_Orca', 'Sorry_Sliders_Board_Game', 'SORTING_BUS', 'SORTING_TRAIN', 'Spectrum_Wall_Mount', 'SPEED_BOAT', 'Sperry_TopSider_pSUFPWQXPp3', 'Sperry_TopSider_tNB9t6YBUf3', 'SpiderMan_Titan_Hero_12Inch_Action_Figure_5Hnn4mtkFsP', 'SpiderMan_Titan_Hero_12Inch_Action_Figure_oo1qph4wwiW', 'Spritz_Easter_Basket_Plastic_Teal', 'Squirrel', 'Squirtin_Barnyard_Friends_4pk', 'Squirt_Strain_Fruit_Basket', 'STACKING_BEAR', 'STACKING_BEAR_V04KKgGBn2A', 'STACKING_RING', 'Starstruck_Tieks_Glittery_Gold_Italian_Leather_Ballet_Flats', 'Star_Wars_Rogue_Squadron_Nintendo_64', 'STEAK_SET', 'Reebok_SL_FLIP_UPDATE', 'Reebok_SMOOTHFLEX_CUSHRUN_20', 'Reebok_SOMERSET_RUN', 'Reebok_STUDIO_BEAT_LOW_V', 'Reebok_TRIPLE_BREAK_LITE', 'Reebok_TURBO_RC', 'Reebok_ULTIMATIC_2V', 'Reebok_VERSA_TRAIN', 'Reebok_ZIGCOOPERSTOWN_QUAG', 'Reebok_ZIGLITE_RUSH', 'Reebok_ZIGLITE_RUSH_AC', 'Reebok_ZIGSTORM', 'Reebok_ZIGTECH_SHARK_MAYHEM360', 'REEF_BANTU', 'REEF_BRAIDED_CUSHION', 'Reef_Star_Cushion_Flipflops_Size_8_Black', 'REEF_ZENFUN', 'Remington_1_12_inch_Hair_Straightener', 'Remington_TStudio_Hair_Dryer', 'Remington_TStudio_Silk_Ceramic_Hair_Straightener_2_Inch_Floating_Plates', 'RESCUE_CREW', 'Reebok_GL_6000', 'Reebok_HIMARA_LTR', 'Reebok_JR_ZIG_COOPERSTOWN_MR', 'Reebok_KAMIKAZE_II_MID', 'Reebok_PUMP_OMNI_LITE_HLS', 'Reebok_REALFLEX_SELECT', 'Reebok_REESCULPT_TRAINER_II', 'Reebok_RETRO_RUSH_2V', 'Reebok_R_CROSSFIT_OLY_UFORM', 'Reebok_R_DANCE_FLASH', 'Reebok_SH_COURT_MID_II', 'Reebok_SH_NEWPORT_LOW', 'Reebok_SH_PRIME_COURT_LOW', 'Poppin_File_Sorter_Pink', 'Poppin_File_Sorter_White', 'POUNDING_MUSHROOMS', 'Predator_LZ_TRX_FG', 'Predito_LZ_TRX_FG_W', 'Progressive_Rubber_Spatulas_3_count', 'ProSport_Harness_to_Booster_Seat', 'Prostate_Optimizer', 'Provence_Bath_Towel_Royal_Blue', 'PUNCH_DROP', 'PUNCH_DROP_TjicLPMqLvz', 'PureCadence_2_Color_HiRskRedNghtlfeSlvrBlckWht_Size_70', 'PureCadence_2_Color_TleBluLmePnchSlvMoodIndgWh_Size_50_EEzAfcBfHHO', 'PureConnect_2_Color_AnthrcteKnckoutPnkGrnGecko_Size_50', 'PureConnect_2_Color_BlckBrllntBluNghtlfeAnthrct_Size_70', 'PureConnect_2_Color_FernNightlifeSilverBlack_Size_70_5w0BYsiogeV', 'PureFlow_2_Color_RylPurHibiscusBlkSlvrWht_Size_50', 'QAbsorb_CoQ10', 'QAbsorb_CoQ10_53iUqjWjW3O', 'QHPomegranate', 'Quercetin_500', 'Racoon', 'Ravenna_4_Color_WhtOlyBluBlkShkOrngSlvRdO_Size_70', 'Rayna_BootieWP', 'PhosphOmega', 'PINEAPPLE_MARACA_6_PCSSET', 'Pinwheel_Pencil_Case', 'Playmates_Industrial_CoSplinter_Teenage_Mutant_Ninja_Turtle_Action_Figure', 'Playmates_nickelodeon_teenage_mutant_ninja_turtles_shredder', 'Poise_Ultimate_Pads_Long', 'Pokmon_Conquest_Nintendo_DS_Game', 'Pokmon_X_Nintendo_3DS_Game', 'Pokmon_Y_Nintendo_3DS_Game', 'Pokémon_Omega_Ruby_Alpha_Sapphire_Dual_Pack_Nintendo_3DS', 'Pokémon_Yellow_Special_Pikachu_Edition_Nintendo_Game_Boy_Color', 'Polar_Herring_Fillets_Smoked_Peppered_705_oz_total', 'Pony_C_Clamp_1440', 'Olive_Kids_Mermaids_Pack_n_Snack_Backpack', 'Olive_Kids_Paisley_Pencil_Case', 'Olive_Kids_Robots_Pencil_Case', 'Olive_Kids_Trains_Planes_Trucks_Bogo_Backpack', 'Olive_Kids_Trains_Planes_Trucks_Munch_n_Lunch_Bag', 'Orbit_Bubblemint_Mini_Bottle_6_ct', 'Organic_Whey_Protein_Unflavored', 'Organic_Whey_Protein_Vanilla', 'Ortho_Forward_Facing', 'Ortho_Forward_Facing_3Q6J2oKJD92', 'Ortho_Forward_Facing_CkAW6rL25xH', 'Ortho_Forward_Facing_QCaor9ImJ2G', 'OVAL_XYLOPHONE', 'OWL_SORTER', 'Office_Depot_Canon_CL211XL_Remanufactured_Ink_Cartridge_TriColor', 'Office_Depot_Canon_CLI36_Remanufactured_Ink_Cartridge_TriColor', 'Office_Depot_Canon_CLI_221BK_Ink_Cartridge_Black_2946B001', 'Office_Depot_Canon_CLI_8CMY_Remanufactured_Ink_Cartridges_Color_Cyan_Magenta_Yellow_3_count', 'Office_Depot_Canon_CLI_8Y_Ink_Cartridge_Yellow_0623B002', 'Office_Depot_Canon_CL_41_Remanufactured_Ink_Cartridge_TriColor', 'Office_Depot_Canon_PG21XL_Remanufactured_Ink_Cartridge_Black', 'Office_Depot_Canon_PGI22_Remanufactured_Ink_Cartridge_Black', 'Office_Depot_Canon_PGI35_Remanufactured_Ink_Cartridge_Black', 'Office_Depot_Canon_PGI5BK_Remanufactured_Ink_Cartridge_Black', 'Office_Depot_Canon_PG_240XL_Ink_Cartridge_Black_5206B001', 'Office_Depot_Dell_Series_11_Remanufactured_Ink_Cartridge_Black', 'Office_Depot_Dell_Series_11_Remanufactured_Ink_Cartridge_TriColor', 'Office_Depot_Dell_Series_1_Remanufactured_Ink_Cartridge_Black', 'Nintendo_2DS_Crimson_Red', 'Nintendo_Mario_Action_Figure', 'Nintendo_Wii_Party_U_with_Controller_Wii_U_Game', 'Nintendo_Yoshi_Action_Figure', 'Nips_Hard_Candy_Rich_Creamy_Butter_Rum_4_oz_1133_g', 'Nordic_Ware_Original_Bundt_Pan', 'Now_Designs_Bowl_Akita_Black', 'Now_Designs_Dish_Towel_Mojave_18_x_28', 'Now_Designs_Snack_Bags_Bicycle_2_count', 'NUTS_BOLTS', 'Object', 'Object_REmvBDJStub', 'Olive_Kids_Birdie_Pack_n_Snack', 'Olive_Kids_Birdie_Sidekick_Backpack', 'Olive_Kids_Butterfly_Garden_Munch_n_Lunch_Bag', 'Olive_Kids_Butterfly_Garden_Pencil_Case', 'Olive_Kids_Dinosaur_Land_Lunch_Box', 'Olive_Kids_Dinosaur_Land_Munch_n_Lunch', 'Olive_Kids_Dinosaur_Land_Pack_n_Snack', 'Olive_Kids_Dinosaur_Land_Sidekick_Backpack', 'Olive_Kids_Game_On_Lunch_Box', 'Olive_Kids_Game_On_Munch_n_Lunch', 'Office_Depot_Dell_Series_5_Remanufactured_Ink_Cartridge_Black', 'Office_Depot_Dell_Series_9_Color_Ink_Ink_Cartridge_MK991_MK993', 'Office_Depot_Dell_Series_9_Ink_Cartridge_Black_MK992', 'Office_Depot_HP_2_Remanufactured_Ink_Cartridges_Color_Cyan_Magenta_Yellow_3_count', 'Office_Depot_HP_564XL_Ink_Cartridge_Black_CN684WN', 'Office_Depot_HP_564XL_Remanufactured_Ink_Cartridges_Color_Cyan_Magenta_Yellow_3_count', 'Office_Depot_HP_61Tricolor_Ink_Cartridge', 'Office_Depot_HP_71_Remanufactured_Ink_Cartridge_Black', 'Office_Depot_HP_74XL75_Remanufactured_Ink_Cartridges_BlackTriColor_2_count', 'Office_Depot_HP_75_Remanufactured_Ink_Cartridge_TriColor', 'Office_Depot_HP_920XL_920_High_Yield_Black_and_Standard_CMY_Color_Ink_Cartridges', 'Office_Depot_HP_932XL_Ink_Cartridge_Black_CN053A', 'Office_Depot_HP_950XL_Ink_Cartridge_Black_CN045AN', 'Office_Depot_HP_96_Remanufactured_Ink_Cartridge_Black', 'Office_Depot_HP_98_Remanufactured_Ink_Cartridge_Black', 'Olive_Kids_Birdie_Lunch_Box', 'Nestl_Skinny_Cow_Heavenly_Crisp_Candy_Bar_Chocolate_Raspberry_6_pack_462_oz_total', 'Netgear_Ac1750_Router_Wireless_Dual_Band_Gigabit_Router', 'Netgear_N750_Wireless_Dual_Band_Gigabit_Router', 'Netgear_Nighthawk_X6_AC3200_TriBand_Gigabit_Wireless_Router', 'New_Super_Mario_BrosWii_Wii_Game', 'Nickelodeon_Teenage_Mutant_Ninja_Turtles_Leonardo', 'Nickelodeon_Teenage_Mutant_Ninja_Turtles_Michelangelo', 'Nickelodeon_Teenage_Mutant_Ninja_Turtles_Raphael', 'Nickelodeon_The_Spongebob_Movie_PopAPart_Spongebob', 'Nightmare_Before_Christmas_Collectors_Edition_Operation', 'Nescafe_Momento_Mocha_Specialty_Coffee_Mix_8_ct', 'NESCAFE_NESCAFE_TC_STKS_DECAF_6_CT', 'Nescafe_Tasters_Choice_Instant_Coffee_Decaf_House_Blend_Light_7_oz', 'Nestle_Candy_19_oz_Butterfinger_Singles_116567', 'Nestle_Carnation_Cinnamon_Coffeecake_Kit_1913OZ', 'Nestle_Nesquik_Chocolate_Powder_Flavored_Milk_Additive_109_Oz_Canister', 'Nestle_Nips_Hard_Candy_Peanut_Butter', 'Nestle_Pure_Life_Exotics_Sparkling_Water_Strawberry_Dragon_Fruit_8_count_12_fl_oz_can', 'Nestle_Pure_Life_Exotics_Sparkling_Water_Strawberry_Dragon_Fruit_8_count_12_fl_oz_can_aX0ygjh3bxi', 'Nestle_Raisinets_Milk_Chocolate_35_oz_992_g', 'Nestle_Skinny_Cow_Dreamy_Clusters_Candy_Dark_Chocolate_6_pack_1_oz_pouches', 'Metallic_Pewter_Tieks_Italian_Leather_Ballet_Flats', 'MINI_EXCAVATOR', 'MINI_FIRE_ENGINE', 'MINI_ROLLER', 'MIRACLE_POUNDING', 'Mist_Wipe_Warmer', 'MK7', 'MODERN_DOLL_FAMILY', 'MONKEY_BOWLING', 'MOSAIC', 'MOVING_MOUSE_PW_6PCSSET', 'My_First_Animal_Tower', 'My_First_Rolling_Lion', 'My_First_Wiggle_Crocodile', 'My_Little_Pony_Princess_Celestia', 'My_Monopoly_Board_Game', 'MY_MOOD_MEMO', 'NAPA_VALLEY_NAVAJO_SANDAL', 'NattoMax', 'Neat_Solutions_Character_Bib_2_pack', 'Nescafe_16Count_Dolce_Gusto_Cappuccino_Capsules', 'Mens_Billfish_3Eye_Boat_Shoe_in_Dark_Tan_wyns9HRcEuH', 'Mens_Billfish_Slip_On_in_Coffee_e8bPKE9Lfgo', 'Mens_Billfish_Slip_On_in_Coffee_nK6AJJAHOae', 'Mens_Billfish_Slip_On_in_Tan_Beige_aaVUk0tNTv8', 'Mens_Billfish_Ultra_Lite_Boat_Shoe_in_Dark_Brown_Blue_c6zDZTtRJr6', 'Mens_Gold_Cup_ASV_2Eye_Boat_Shoe_in_Cognac_Leather', 'Mens_Gold_Cup_ASV_Capetown_Penny_Loafer_in_Black_EjPnk3E8fCs', 'Mens_Gold_Cup_ASV_Capetown_Penny_Loafer_in_Black_GkQBKqABeQN', 'Mens_Gold_Cup_ASV_Dress_Casual_Venetian_in_Dark_Brown_Leather', 'Mens_Largo_Slip_On_in_Taupe_gooyS417q4R', 'Mens_Mako_Canoe_Moc_2Eye_Boat_Shoe_in_Coffee_9d05GG33QQQ', 'Little_House_on_the_Prairie_Season_Two_5_Discs_Includes_Digital', 'Logitech_Ultimate_Ears_Boom_Wireless_Speaker_Night_Black', 'Lovable_Huggable_Cuddly_Boutique_Teddy_Bear_Beige', 'Lovestruck_Tieks_Glittery_Rose_Gold_Italian_Leather_Ballet_Flats', 'LTyrosine', 'Luigis_Mansion_Dark_Moon_Nintendo_3DS_Game', 'Lutein', 'Mad_Gab_Refresh_Card_Game', 'Magnifying_Glassassrt', 'Marc_Anthony_Skip_Professional_Oil_of_Morocco_Conditioner_with_Argan_Oil', 'Marc_Anthony_Strictly_Curls_Curl_Envy_Perfect_Curl_Cream_6_fl_oz_bottle', 'Marc_Anthony_True_Professional_Oil_of_Morocco_Argan_Oil_Treatment', 'Marc_Anthony_True_Professional_Strictly_Curls_Curl_Defining_Lotion', 'Mario_Luigi_Dream_Team_Nintendo_3DS_Game', 'Mario_Party_9_Wii_Game', 'Markings_Desk_Caddy', 'Lavender_Snake_Tieks_Snake_Print_Ballet_Flats', 'Leap_Frog_Paint_Dabber_Dot_Art_5_paint_bottles', 'LEGO_5887_Dino_Defense_HQ', 'LEGO_Bricks_More_Creative_Suitcase', 'LEGO_City_Advent_Calendar', 'LEGO_Creationary_Game', 'LEGO_Creationary_Game_ZJa163wlWp2', 'LEGO_Duplo_Build_and_Play_Box_4629', 'LEGO_Duplo_Creative_Animals_10573', 'Lego_Friends_Advent_Calendar', 'Lego_Friends_Mia', 'LEGO_Fusion_Set_Town_Master', 'LEGO_Star_Wars_Advent_Calendar', 'Lenovo_Yoga_2_11', 'LEUCIPPUS_ADIPURE', 'Little_Big_Planet_3_Plush_Edition', 'Little_Debbie_Chocolate_Cupcakes_8_ct', 'Little_Debbie_Cloud_Cakes_10_ct', 'JBL_Charge_Speaker_portable_wireless_wired_Green', 'JS_WINGS_20_BLACK_FLAG', 'JUICER_SET', 'JUNGLE_HEIGHT', 'Justified_The_Complete_Fourth_Season_3_Discs_DVD', 'Just_For_Men_Mustache_Beard_Brushin_Hair_Color_Gel_Kit_Jet_Black_M60', 'Just_For_Men_Mustache_Beard_Brushin_Hair_Color_Gel_MediumDark_Brown_M40', 'Just_For_Men_ShampooIn_Haircolor_Jet_Black_60', 'Just_For_Men_ShampooIn_Haircolor_Light_Brown_25', 'Just_For_Men_Shampoo_In_Haircolor_Darkest_Brown_50', 'Kanex_MultiSync_Wireless_Keyboard', 'Kid_Icarus_Uprising_Nintendo_3DS_Game', 'KID_ROOM_FURNITURE_SET_1', 'Kingston_DT4000MR_G2_Management_Ready_USB_64GB', 'KITCHEN_FURNITURE_SET_1', 'KITCHEN_SET_CLASSIC_40HwCHfeG0H', 'Kong_Puppy_Teething_Rubber_Small_Pink', 'Kotex_U_Barely_There_Liners_Thin_60_count', 'Kotex_U_Tween_Pads_16_pads', 'Kotobuki_Saucer_Dragon_Fly', 'Krill_Oil', 'KS_Chocolate_Cube_Box_Assortment_By_Neuhaus_2010_Ounces', 'LACING_SHEEP', 'Lactoferrin', 'LADYBUG_BEAD', 'Markings_Letter_Holder', 'Mens_Bahama_in_White_vSwvGMCo32f', 'Mens_Mako_Canoe_Moc_2Eye_Boat_Shoe_in_Coffee_K9e8FoV73uZ', 'Metallic_Gold_Tieks_Italian_Leather_Ballet_Flats', 'Nescafe_Memento_Latte_Caramel_8_08_oz_23_g_packets_64_oz_184_g', 'Nestl_Crunch_Girl_Scouts_Cookie_Flavors_Caramel_Coconut_78_oz_box', 'Nikon_1_AW1_w11275mm_Lens_Silver', 'Ocedar_Snap_On_Dust_Pan_And_Brush_1_ct', 'Office_Depot_Dell_Series_1_Remanufactured_Ink_Cartridge_TriColor', 'Olive_Kids_Birdie_Munch_n_Lunch', 'Olive_Kids_Game_On_Pack_n_Snack', 'OXO_Cookie_Spatula', 'Little_Debbie_Donut_Sticks_6_cake_donuts_10_oz_total', 'Perricone_MD_Best_of_Perricone_7Piece_Collection_MEGsO6GIsyL', 'Great_Jones_Wingtip_j5NV8GRnitM', 'Great_Jones_Wingtip_kAqSg6EgG0I', 'Great_Jones_Wingtip_wxH3dbtlvBC', 'Grreatv_Choice_Dog_Bowl_Gray_Bones_Plastic_20_fl_oz_total', 'Grreat_Choice_Dog_Double_Dish_Plastic_Blue', 'Guardians_of_the_Galaxy_Galactic_Battlers_Rocket_Raccoon_Figure', 'HAMMER_BALL', 'HAMMER_PEG', 'HAPPY_ENGINE', 'Hasbro_Cranium_Performance_and_Acting_Game', 'Hasbro_Dont_Wake_Daddy_Board_Game', 'Hasbro_Dont_Wake_Daddy_Board_Game_NJnjGna4u1a', 'Hasbro_Life_Board_Game', 'Hasbro_Monopoly_Hotels_Game', 'Hasbro_Trivial_Pursuit_Family_Edition_Game', 'HeavyDuty_Flashlight', 'Hefty_Waste_Basket_Decorative_Bronze_85_liter', 'HELICOPTER', 'Hey_You_Pikachu_Nintendo_64', 'Hilary', 'Fresca_Peach_Citrus_Sparkling_Flavored_Soda_12_PK', 'Frozen_Olafs_In_Trouble_PopOMatic_Game', 'Frozen_Olafs_In_Trouble_PopOMatic_Game_OEu83W9T8pD', 'Frozen_Scrabble_Jr', 'Fruity_Friends', 'FRUIT_VEGGIE_DOMINO_GRADIENT', 'FRUIT_VEGGIE_MEMO_GRADIENT', 'Fujifilm_instax_SHARE_SP1_10_photos', 'Full_Circle_Happy_Scraps_Out_Collector_Gray', 'FYW_ALTERNATION', 'FYW_DIVISION', 'GARDEN_SWING', 'GEARS_PUZZLES_STANDARD_gcYxhNHhKlI', 'GEOMETRIC_PEG_BOARD', 'GEOMETRIC_SORTING_BOARD', 'GEOMETRIC_SORTING_BOARD_MNi4Rbuz9vj', 'Germanium_GE132', 'Ghost_6_Color_BlckWhtLavaSlvrCitrus_Size_80', 'Ghost_6_Color_MdngtDenmPomBrtePnkSlvBlk_Size_50', 'Ghost_6_GTX_Color_AnthBlckSlvrFernSulphSprng_Size_80', 'DPC_Thinsulate_Isolate_Gloves_Brown', 'DPC_tropical_Trends_Hat', 'DRAGON_W', 'D_ROSE_45', 'D_ROSE_773_II_hvInJwJ5HUD', 'D_ROSE_773_II_Kqclsph05pE', 'D_ROSE_ENGLEWOOD_II', 'Eat_to_Live_The_Amazing_NutrientRich_Program_for_Fast_and_Sustained_Weight_Loss_Revised_Edition_Book', 'Ecoforms_Cup_B4_SAN', 'Ecoforms_Garden_Pot_GP16ATurquois', 'Ecoforms_Planter_Bowl_Cole_Hardware', 'Ecoforms_Planter_Pot_GP12AAvocado', 'Ecoforms_Planter_Pot_QP6Ebony', 'Ecoforms_Plant_Bowl_Atlas_Low', 'Ecoforms_Plant_Bowl_Turquoise_7', 'Ecoforms_Plant_Container_12_Pot_Nova', 'Ecoforms_Plant_Container_B4_Har', 'Ecoforms_Plant_Container_FB6_Tur', 'Ecoforms_Plant_Container_GP16AMOCHA', 'CoQ10_wSSVoxVppVD', 'Corningware_CW_by_Corningware_3qt_Oblong_Casserole_Dish_Blue', 'Court_Attitude', 'Craftsman_Grip_Screwdriver_Phillips_Cushion', 'Crayola_Bonus_64_Crayons', 'Crayola_Crayons_120_crayons', 'Crayola_Crayons_24_count', 'Crayola_Crayons_Washable_24_crayons', 'Crayola_Model_Magic_Modeling_Material_Single_Packs_6_pack_05_oz_packs', 'Crayola_Model_Magic_Modeling_Material_White_3_oz', 'Crayola_Washable_Fingerpaint_Red_Blue_Yellow_3_count_8_fl_oz_bottes_each', 'Crayola_Washable_Sidewalk_Chalk_16_pack', 'Crayola_Washable_Sidewalk_Chalk_16_pack_wDZECiw7J6s', 'FARM_ANIMAL_9GyfdcPyESK', 'FemDophilus', 'Final_Fantasy_XIV_A_Realm_Reborn_60Day_Subscription', 'Firefly_Clue_Board_Game', 'FIRE_ENGINE', 'FIRE_TRUCK', 'FisherPrice_Make_A_Match_Game_Thomas_Friends', 'Fisher_price_Classic_Toys_Buzzy_Bee', 'FISHING_GAME', 'Focus_8643_Lime_Squeezer_10x35x188_Enamelled_Aluminum_Light', 'Folic_Acid', 'FOOD_BEVERAGE_SET', 'Footed_Bowl_Sand', 'Canon_Pixma_Ink_Cartridge_251_M', 'Canon_Pixma_Ink_Cartridge_8', 'Canon_Pixma_Ink_Cartridge_8_Green', 'Canon_Pixma_Ink_Cartridge_8_Red', 'Canon_Pixma_Ink_Cartridge_Cyan_251', 'CARSII', 'CAR_CARRIER_TRAIN', 'Cascadia_8_Color_AquariusHibscsBearingSeaBlk_Size_50', 'CASTLE_BLOCKS', 'Central_Garden_Flower_Pot_Goo_425', 'Chefmate_8_Frypan', 'Chef_Style_Round_Cake_Pan_9_inch_pan', 'Chelsea_BlkHeelPMP_DwxLtZNxLZZ', 'Chelsea_lo_fl_rdheel_nQ0LPNF1oMw', 'Chelsea_lo_fl_rdheel_zAQrnhlEfw8', 'Crazy_Shadow_2', 'Crazy_Shadow_2_oW4Jd10HFFr', 'Cream_Tieks_Italian_Leather_Ballet_Flats', 'Creatine_Monohydrate', 'CREATIVE_BLOCKS_35_MM', 'Crosley_Alarm_Clock_Vintage_Metal', 'Crunch_Girl_Scouts_Candy_Bars_Peanut_Butter_Creme_78_oz_box', 'Curver_Storage_Bin_Black_Small', 'DANCING_ALLIGATOR', 'DANCING_ALLIGATOR_zoWBjc0jbTs', 'Dell_Ink_Cartridge', 'Dell_Ink_Cartridge_Yellow_31', 'Dell_Series_9_Color_Ink_Cartridge_MK993_High_Yield', 'Design_Ideas_Drawer_Store_Organizer', 'Asus_Z87PRO_Motherboard_ATX_LGA1150_Socket', 'Asus_Z97AR_LGA_1150_Intel_ATX_Motherboard', 'Asus_Z97IPLUS_Motherboard_Mini_ITX_LGA1150_Socket', 'Avengers_Gamma_Green_Smash_Fists', 'Avengers_Thor_PLlrpYniaeB', 'Azure_Snake_Tieks_Leather_Snake_Print_Ballet_Flats', 'BABY_CAR', 'Baby_Elements_Stacking_Cups', 'BAGEL_WITH_CHEESE', 'BAKING_UTENSILS', 'BALANCING_CACTUS', 'Balderdash_Game', 'BATHROOM_CLASSIC', 'BATHROOM_FURNITURE_SET_1', 'BEDROOM_CLASSIC', 'BEDROOM_CLASSIC_Gi22DjScTVS', 'BEDROOM_NEO', 'Beetle_Adventure_Racing_Nintendo_64', 'Beta_Glucan', 'Beyonc_Life_is_But_a_Dream_DVD', 'BIA_Cordon_Bleu_White_Porcelain_Utensil_Holder_900028', 'Brisk_Iced_Tea_Lemon_12_12_fl_oz_355_ml_cans_144_fl_oz_426_lt', 'Brother_Ink_Cartridge_Magenta_LC75M', 'Brother_LC_1053PKS_Ink_Cartridge_CyanMagentaYellow_1pack', 'Brother_Printing_Cartridge_PC501', 'BUILD_A_ROBOT', 'BUILD_A_ZOO', 'BUNNY_RACER', 'BUNNY_RATTLE', 'California_Navy_Tieks_Italian_Leather_Ballet_Flats', 'Calphalon_Kitchen_Essentials_12_Cast_Iron_Fry_Pan_Black', 'Canon_225226_Ink_Cartridges_BlackColor_Cyan_Magenta_Yellow_6_count', 'Canon_Ink_Cartridge_Green_6', 'ASICS_GEL1140V_WhiteRoyalSilver', 'ASICS_GELAce_Pro_Pearl_WhitePink', 'ASICS_GELBlur33_20_GS_BlackWhiteSafety_Orange', 'ASICS_GELBlur33_20_GS_Flash_YellowHot_PunchSilver', 'ASICS_GELChallenger_9_Royal_BlueWhiteBlack', 'ASICS_GELDirt_Dog_4_SunFlameBlack', 'ASICS_GELLinksmaster_WhiteCoffeeSand', 'ASICS_GELLinksmaster_WhiteRasberryGunmetal', 'ASICS_GELLinksmaster_WhiteSilverCarolina_Blue', 'ASICS_GELResolution_5_Flash_YellowBlackSilver', 'ASICS_GELTour_Lyte_WhiteOrchidSilver', 'ASICS_HyperRocketgirl_SP_5_WhiteMalibu_BlueBlack', 'ASSORTED_VEGETABLE_SET', 'Asus_80211ac_DualBand_Gigabit_Wireless_Router_RTAC68R', 'Asus_M5A78LMUSB3_Motherboard_Micro_ATX_Socket_AM3', 'Asus_M5A99FX_PRO_R20_Motherboard_ATX_Socket_AM3', 'Asus_Sabertooth_990FX_20_Motherboard_ATX_Socket_AM3', 'Asus_Sabertooth_Z97_MARK_1_Motherboard_ATX_LGA1150_Socket', 'Mens_Mako_Canoe_Moc_2Eye_Boat_Shoe_in_OysterTaupe_otyRrfvPMiA', 'Mens_RR_Moc_in_Navy_Suede_vmFfijhBzL3', 'Mens_Santa_Cruz_Thong_in_Chocolate_La1fo2mAovE', 'Mens_Santa_Cruz_Thong_in_Chocolate_lvxYW7lek6B', 'Mens_Santa_Cruz_Thong_in_Tan_r59C69daRPh', 'Mens_Striper_Sneaker_in_White_rnp8HUli59Y', 'Mens_Tremont_Kiltie_Tassel_Loafer_in_Black_Amaretto', 'Mens_Tremont_Kiltie_Tassel_Loafer_in_Black_Amaretto_FT0I9OjSA6O', 'Mens_Tremont_Kiltie_Tassel_Loafer_in_Black_Amaretto_rCdzRZqgCnI', 'Mens_Wave_Driver_Kiltie_Moc_in_Tan_Leather'])\n",
      "dict_keys(['model', 'name', 'description', 'version', 'authors', 'legal', 'annotations', 'compatibilities', 'categories'])\n"
     ]
    }
   ],
   "source": [
    "print(metadata.keys())\n",
    "print(metadata[list(metadata.keys())[0]].keys())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "# get all categories\n",
    "all_categories = set()\n",
    "for object_id in metadata.keys():\n",
    "    if 'categories' in metadata[object_id].keys():\n",
    "        categories:dict = metadata[object_id]['categories']\n",
    "        for category in categories.values():\n",
    "            all_categories.add(category)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'Action Figures',\n",
       " 'Bag',\n",
       " 'Board Games',\n",
       " 'Bottles and Cans and Cups',\n",
       " 'Camera',\n",
       " 'Car Seat',\n",
       " 'Consumer Goods',\n",
       " 'Hat',\n",
       " 'Headphones',\n",
       " 'Keyboard',\n",
       " 'Legos',\n",
       " 'Media Cases',\n",
       " 'Mouse',\n",
       " 'Shoe',\n",
       " 'Stuffed Toys',\n",
       " 'Toys'}"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "all_categories"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Filter container objects "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Filtered by name keywords, number of candidate objects: 148\n"
     ]
    }
   ],
   "source": [
    "# filter by name key words\n",
    "cotainer_key_words = [\"bowl\", \"plate\", \"cup\", \"mug\", \"jar\", \"container\", \"pot\", \"pan\", \"tray\", \"bucket\", \"basket\", \"saucer\"]\n",
    "\n",
    "container_ids = []\n",
    "\n",
    "for object_id in metadata.keys():   \n",
    "    # check if object id contains container key words\n",
    "    if np.any([key_word in object_id.lower() for key_word in cotainer_key_words]):\n",
    "\n",
    "        container_ids.append(object_id)\n",
    "\n",
    "print(f\"Filtered by name keywords, number of candidate objects: {len(container_ids)}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████| 148/148 [00:09<00:00, 14.87it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Filtered by size and convexity, number of candidate objects: 148\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\n"
     ]
    }
   ],
   "source": [
    "# check if the container mesh size fits the table width 0.8m and is not convex\n",
    "container_ids_filtered_by_mesh = []\n",
    "\n",
    "for object_id in tqdm.tqdm(container_ids):\n",
    "    mesh_path = os.path.join(google_scans_path, object_id, \"meshes\", \"model.obj\")\n",
    "    mesh = trimesh.load(mesh_path)\n",
    "    mesh_dimensions = getMeshDimensions(mesh)\n",
    "    if np.all(mesh_dimensions < 0.8) and not mesh.is_convex:\n",
    "        container_ids_filtered_by_mesh.append(object_id)\n",
    "\n",
    "print(f\"Filtered by size and convexity, number of candidate objects: {len(container_ids_filtered_by_mesh)}\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "\n",
    "# container_thumbnail_path = os.path.join(output_path, \"container_thumbnails\")\n",
    "container_thumbnail_path = \"../../data/google_scanned_object/container_thumbnails\"\n",
    "\n",
    "if not os.path.exists(container_thumbnail_path):\n",
    "    os.makedirs(container_thumbnail_path)\n",
    "# collect_thumbnails(google_scans_path, container_thumbnail_path, container_ids_filtered_by_mesh)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Filtered by manual selection, number of candidate objects: 41\n"
     ]
    }
   ],
   "source": [
    "# filter containers manually and read the remaining thumbnails\n",
    "left_thumbnails = os.listdir(container_thumbnail_path)\n",
    "filtered_containers = [thumbnail.split(\".\")[0] for thumbnail in left_thumbnails]\n",
    "print( f\"Filtered by manual selection, number of candidate objects: {len(filtered_containers)}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Cannot find category for Smith_Hawken_Woven_BasketTray_Organizer_with_3_Compartments_95_x_9_x_13\n",
      "Cannot find category for Chefmate_8_Frypan\n"
     ]
    }
   ],
   "source": [
    "# generate container metadata\n",
    "container_metadata = {\n",
    "    \"categories\": {},\n",
    "    \"objects\": {}\n",
    "}\n",
    "\n",
    "# predefined container categories\n",
    "container_categories = [\"bowl\", \"plate\", \"container\", \"pot\", \"pan\", \"tray\", \"basket\", \"saucer\", \"planter\"]\n",
    "\n",
    "# assign categories to containers\n",
    "for container in filtered_containers:\n",
    "    container_metadata[\"objects\"][container] = {}\n",
    "    for category in container_categories:\n",
    "        if category in container.lower().split(\"_\"):\n",
    "            container_metadata[\"objects\"][container][\"category\"] = category\n",
    "            # print(f\"Find category {category} for {container}\")\n",
    "            break \n",
    "    if \"category\" not in container_metadata[\"objects\"][container].keys():\n",
    "        print(f\"Cannot find category for {container}\")\n",
    "    \n",
    "# post-process for corner-case categories\n",
    "container_metadata[\"objects\"][\"Smith_Hawken_Woven_BasketTray_Organizer_with_3_Compartments_95_x_9_x_13\"][\"category\"] = \"basket\"\n",
    "container_metadata[\"objects\"][\"Chefmate_8_Frypan\"][\"category\"] = \"pan\"\n",
    "\n",
    "# replace container with planter (only plant_container appears in the dataset)\n",
    "container_categories.remove(\"container\")\n",
    "for container in container_metadata[\"objects\"].keys():\n",
    "    if container_metadata[\"objects\"][container][\"category\"] == \"container\":\n",
    "        container_metadata[\"objects\"][container][\"category\"] = \"planter\"\n",
    "\n",
    "# check if any remaining container has no category\n",
    "for container in container_metadata[\"objects\"].keys():\n",
    "    assert \"category\" in container_metadata[\"objects\"][container]\n",
    "\n",
    "# create category to container mapping\n",
    "for container in container_metadata[\"objects\"].keys():\n",
    "    category = container_metadata[\"objects\"][container][\"category\"]\n",
    "    if category not in container_metadata[\"categories\"].keys():\n",
    "        container_metadata[\"categories\"][category] = []\n",
    "    container_metadata[\"categories\"][category].append(container)\n",
    "\n",
    "\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████| 41/41 [00:03<00:00, 11.86it/s]\n"
     ]
    }
   ],
   "source": [
    "# calculate bounding box for containers\n",
    "for container in tqdm.tqdm(filtered_containers):\n",
    "    mesh_path = os.path.join(google_scans_path, container, \"meshes\", \"model.obj\")\n",
    "    mesh = trimesh.load(mesh_path)\n",
    "    mesh_dimensions = getMeshDimensions(mesh)\n",
    "    mesh_bbox_center = getMeshCenter(mesh)\n",
    "    container_metadata[\"objects\"][container][\"bbox_size\"] = mesh_dimensions.tolist()\n",
    "    container_metadata[\"objects\"][container][\"bbox_center\"] = mesh_bbox_center.tolist()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "# add container model_name \n",
    "with open(\"../../data/google_scanned_object/model_name_manual.json\", \"r\") as f:\n",
    "    model_name_mapping = json.load(f)\n",
    "\n",
    "for container in filtered_containers:\n",
    "    container_metadata[\"objects\"][container][\"model_name\"] = model_name_mapping[container]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 75,
   "metadata": {},
   "outputs": [],
   "source": [
    "# count number of objects in each category\n",
    "# category_count = { category: 0 for category in container_categories}\n",
    "# for container in container_metadata[\"objects\"].keys():\n",
    "#     category = container_metadata[\"objects\"][container][\"category\"]\n",
    "#     if category in category_count.keys():\n",
    "#         category_count[category] += 1\n",
    "#     else:\n",
    "#         category_count[category] = 1\n",
    "\n",
    "# print(category_count)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "# save bounding box and category information to json file\n",
    "# with open(os.path.join(output_path, \"container_metadata.json\"), 'w') as f:\n",
    "#     json.dump(container_metadata, f, indent=4)\n",
    "    "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Filter pickable objects "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "# generate mesh bounding box size for all google scan objects \n",
    "# mesh_dimensions = {}\n",
    "# for object_id in tqdm.tqdm(object_ids):\n",
    "#     mesh_path = os.path.join(google_scans_path, object_id, \"meshes\", \"model.obj\")\n",
    "#     mesh = trimesh.load(mesh_path)\n",
    "#     mesh_dimensions[object_id] = getMeshDimensions(mesh).tolist()\n",
    "\n",
    "# # save mesh dimensions to json file\n",
    "# with open(os.path.join(output_path, \"mesh_dimensions.json\"), 'w') as f:\n",
    "#     json.dump(mesh_dimensions, f)\n",
    "\n",
    "# load mesh dimensions from json file \n",
    "with open(os.path.join(output_path, \"mesh_dimensions.json\"), 'r') as f:\n",
    "    mesh_dimensions = json.load(f)\n",
    "    \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Number of small objects: 17\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████| 17/17 [00:00<00:00, 383.96it/s]\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "{}"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# filter object size by its mesh size\n",
    "# panda emika franka roboto gripper max width: 80mm\n",
    "# small_objects: all shapes with max dimension < 0.08m\n",
    "small_object_ids = []\n",
    "for object_id in object_ids:\n",
    "    if np.all(np.array(mesh_dimensions[object_id]) < 0.08):\n",
    "        small_object_ids.append(object_id)\n",
    "\n",
    "print(f\"Number of small objects: {len(small_object_ids)}\")\n",
    "\n",
    "# generate thumbnails for small objects\n",
    "small_object_thumbnail_path = os.path.join(output_path, \"small_object_thumbnails\")\n",
    "if not os.path.exists(small_object_thumbnail_path):\n",
    "    os.makedirs(small_object_thumbnail_path)\n",
    "collect_thumbnails(google_scans_path, small_object_thumbnail_path, small_object_ids)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Number of medium objects: 82\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████| 82/82 [00:00<00:00, 374.58it/s]\n"
     ]
    }
   ],
   "source": [
    "# medium objects: all shapes with at most one dimension > 0.08m and all shapes with max dimension < 0.12m \n",
    "if True:\n",
    "    medium_object_ids = []\n",
    "    for object_id in object_ids:\n",
    "        if np.sum(np.array(mesh_dimensions[object_id]) > 0.08) <= 1 and np.all(np.array(mesh_dimensions[object_id]) < 0.12):\n",
    "            medium_object_ids.append(object_id)\n",
    "\n",
    "    print(f\"Number of medium objects: {len(medium_object_ids)}\")\n",
    "\n",
    "    # generate thumbnails for medium objects\n",
    "    medium_object_thumbnail_path = os.path.join(output_path, \"medium_object_thumbnails\")\n",
    "    if not os.path.exists(medium_object_thumbnail_path):\n",
    "        os.makedirs(medium_object_thumbnail_path)\n",
    "    collect_thumbnails(google_scans_path, medium_object_thumbnail_path, medium_object_ids)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 95,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Number of large objects: 78\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████| 78/78 [00:00<00:00, 259.74it/s]\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "{}"
      ]
     },
     "execution_count": 95,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# large objects: all shapes with max dimension < 0.12m and no in previous two categories\n",
    "if False:\n",
    "    large_object_ids = []\n",
    "    for object_id in object_ids:\n",
    "        if np.all(np.array(mesh_dimensions[object_id]) < 0.12) and object_id not in small_object_ids and object_id not in medium_object_ids:\n",
    "            large_object_ids.append(object_id)\n",
    "\n",
    "    print(f\"Number of large objects: {len(large_object_ids)}\")\n",
    "\n",
    "    # generate thumbnails for large objects\n",
    "    large_object_thumbnail_path = os.path.join(output_path, \"large_object_thumbnails\")\n",
    "    if not os.path.exists(large_object_thumbnail_path):\n",
    "        os.makedirs(large_object_thumbnail_path)\n",
    "    collect_thumbnails(google_scans_path, large_object_thumbnail_path, large_object_ids)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Manually select objects from generated thumbnails"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "# generate object_metadata.json from selected thumbnails\n",
    "object_metadata = {\n",
    "    \"categories\": {},\n",
    "    \"objects\": {}\n",
    "}\n",
    "\n",
    "\n",
    "# get selected objects from thumbnails folder\n",
    "thumbnail_dir = os.path.join(output_path, \"object_thumbnails\")\n",
    "selected_objects = [thumbnail.split(\".\")[0] for thumbnail in os.listdir(thumbnail_dir)]\n",
    "\n",
    "# load mapping from model_id to model_name\n",
    "with open(\"../../data/google_scanned_object/model_name_manual.json\", 'r') as f:\n",
    "    model_name_mapping = json.load(f)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "  0%|          | 0/24 [00:00<?, ?it/s]"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████| 24/24 [00:01<00:00, 13.34it/s]\n"
     ]
    }
   ],
   "source": [
    "\n",
    "# predefined object categories\n",
    "object_categories = [\"bottle\", \"box\", \"toy\", \"mug\"]\n",
    "\n",
    "# raw categories annotations are noisy and not consistent\n",
    "# from metadata get object category\n",
    "# for object_id in selected_objects:\n",
    "#     object_metadata[\"objects\"][object_id] = {}\n",
    "#     if 'categories' in metadata[object_id].keys():\n",
    "#         categories:dict = metadata[object_id]['categories']\n",
    "#         for category in categories.values():\n",
    "#             object_metadata[\"objects\"][object_id][\"category\"] = category\n",
    "#             break \n",
    "#     if \"category\" not in object_metadata[\"objects\"][object_id].keys():\n",
    "#         print(f\"Cannot find category for {object_id}\")\n",
    "\n",
    "# annotate object category manually\n",
    "category_mapping = {\n",
    "    \"bottle\": [\n",
    "        \"5_HTP\", \n",
    "        \"AllergenFree_JarroDophilus\", \n",
    "        \"Beta_Glucan\", \n",
    "        \"CoQ10\", \n",
    "        \"Germanium_GE132\", \n",
    "        \"Hyaluronic_Acid\"\n",
    "        ],\n",
    "    \"box\": [\n",
    "        \"FemDophilus\", \n",
    "        \"Granimals_20_Wooden_ABC_Blocks_Wagon_85VdSftGsLi\", \n",
    "        \"JarroSil_Activated_Silicon\", \n",
    "        \"Perricone_MD_Face_Finishing_Moisturizer\", \n",
    "        \"Perricone_MD_Firming_Neck_Therapy_Treatment\",\n",
    "        \"Perricone_MD_Hypoallergenic_Firming_Eye_Cream_05_oz\",\n",
    "        \"Perricone_MD_Neuropeptide_Firming_Moisturizer\",\n",
    "        \"Perricone_MD_No_Bronzer_Bronzer\",\n",
    "        \"Perricone_MD_No_Lipstick_Lipstick\",\n",
    "        \"Phillips_Caplets_Size_24\"\n",
    "        ],\n",
    "    \"toy\": [\n",
    "        \"Android_Figure_Panda\", \n",
    "        \"Great_Dinos_Triceratops_Toy\",\n",
    "        \"Nintendo_Mario_Action_Figure\",\n",
    "        \"Schleich_Lion_Action_Figure\",\n",
    "        \"SCHOOL_BUS\",\n",
    "        \"Thomas_Friends_Wooden_Railway_Talking_Thomas_z7yi7UFHJRj\",\n",
    "        \"Toysmith_Windem_Up_Flippin_Animals_Dog\"\n",
    "    ],\n",
    "    \"mug\": [\n",
    "        \"ACE_Coffee_Mug_Kristen_16_oz_cup\",\n",
    "        \"Cole_Hardware_Mug_Classic_Blue\",\n",
    "        \"Room_Essentials_Mug_White_Yellow\",\n",
    "        \"Threshold_Porcelain_Coffee_Mug_All_Over_Bead_White\"\n",
    "    ]\n",
    "}\n",
    "\n",
    "object_metadata[\"categories\"] = {\n",
    "    \"bottle\": [],\n",
    "    \"box\": [],\n",
    "    \"toy\": [],\n",
    "    \"mug\": []\n",
    "}\n",
    "\n",
    "# create category and bounding box size for each object \n",
    "for object_id in tqdm.tqdm(selected_objects):\n",
    "    mesh_path = os.path.join(google_scans_path, object_id, \"meshes\", \"model.obj\")\n",
    "    mesh = trimesh.load(mesh_path)\n",
    "    mesh_dimensions = getMeshDimensions(mesh)\n",
    "    mesh_bbox_center = getMeshCenter(mesh)\n",
    "    object_metadata[\"objects\"][object_id] = {}\n",
    "    object_metadata[\"objects\"][object_id][\"bbox_size\"] = mesh_dimensions.tolist() \n",
    "    object_metadata[\"objects\"][object_id][\"bbox_center\"] = mesh_bbox_center.tolist()\n",
    "    object_metadata[\"objects\"][object_id][\"model_name\"] = model_name_mapping[object_id]\n",
    "\n",
    "for category in category_mapping.keys():\n",
    "    for object_id in category_mapping[category]:\n",
    "        if object_id in selected_objects:\n",
    "            object_metadata[\"objects\"][object_id][\"category\"] = category\n",
    "            object_metadata[\"categories\"][category].append(object_id)\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "# save bounding box and category information to json file\n",
    "# with open(os.path.join(output_path, \"object_metadata.json\"), 'w') as f:\n",
    "#     json.dump(object_metadata, f, indent=4)\n",
    "    "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Collect selected models into path "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████| 41/41 [00:01<00:00, 23.25it/s]\n"
     ]
    }
   ],
   "source": [
    "# copy selected containers to target directory\n",
    "metadata_file = os.path.join(output_path, \"container_metadata.json\")\n",
    "target_dir = os.path.join(output_path, \"models\")\n",
    "if not os.path.exists(target_dir):\n",
    "    os.makedirs(target_dir)\n",
    "\n",
    "with open(metadata_file, 'r') as f:\n",
    "    metadata = json.load(f)\n",
    "\n",
    "# copy selected models to target directory\n",
    "if False:\n",
    "    for model in tqdm.tqdm(metadata[\"objects\"].keys()):\n",
    "        model_dir = os.path.join(google_scans_path, model)\n",
    "        target_model_dir = os.path.join(target_dir, model)\n",
    "        os.system(\"cp -r {} {}\".format(model_dir, target_model_dir))\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "# copy selected objects to target directory\n",
    "metadata_file = os.path.join(output_path, \"object_metadata.json\")\n",
    "target_dir = os.path.join(output_path, \"models\")\n",
    "if not os.path.exists(target_dir):\n",
    "    os.makedirs(target_dir)\n",
    "\n",
    "with open(metadata_file, 'r') as f:\n",
    "    metadata = json.load(f)\n",
    "\n",
    "# copy selected objects to target directory\n",
    "if False:\n",
    "    for model in tqdm.tqdm(metadata[\"objects\"].keys()):\n",
    "        model_dir = os.path.join(google_scans_path, model)\n",
    "        target_model_dir = os.path.join(target_dir, model)\n",
    "        os.system(\"cp -r {} {}\".format(model_dir, target_model_dir))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Generate collaged image of thumbnails"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "# collect all thumbnails in container_thumbnails folder, and collage as one image\n",
    "from PIL import Image\n",
    "import matplotlib.pyplot as plt\n",
    "import matplotlib.image as mpimg\n",
    "import numpy as np\n",
    "import os\n",
    "import math\n",
    "\n",
    "def collage(thumbnail_dir, output_path):\n",
    "\n",
    "    # Get a list of all the thumbnail file names in the folder\n",
    "    thumbnail_files = os.listdir(thumbnail_dir)\n",
    "\n",
    "    # Calculate the number of thumbnails in the folder\n",
    "    num_thumbnails = len(thumbnail_files)\n",
    "\n",
    "    # Calculate the size of the square image needed to fit all the thumbnails\n",
    "    image_size = int(math.ceil(math.sqrt(num_thumbnails)))\n",
    "\n",
    "    # Create a new blank image to use as the canvas for the collage\n",
    "    canvas = Image.new('RGB', (image_size * 100, image_size * 100), (255, 255, 255))\n",
    "\n",
    "    # Loop through each thumbnail file and paste it onto the canvas\n",
    "    for i in range(num_thumbnails):\n",
    "        # Open the thumbnail image\n",
    "        thumbnail = Image.open(os.path.join(thumbnail_dir, thumbnail_files[i]))\n",
    "        \n",
    "        # Resize the thumbnail to 100x100 pixels\n",
    "        thumbnail = thumbnail.resize((100, 100))\n",
    "        \n",
    "        # Calculate the x and y coordinates of where to paste the thumbnail onto the canvas\n",
    "        x = (i % image_size) * 100\n",
    "        y = (i // image_size) * 100\n",
    "        \n",
    "        # Paste the thumbnail onto the canvas\n",
    "        canvas.paste(thumbnail, (x, y))\n",
    "\n",
    "    # Save the canvas image\n",
    "    canvas.save(output_path)\n",
    "\n",
    "# save container thumbnails as one image\n",
    "thumbnail_dir = os.path.join(output_path, \"container_thumbnails\")\n",
    "container_collage_path = os.path.join(output_path, \"container_collage.jpg\")\n",
    "collage(thumbnail_dir, container_collage_path)\n",
    "\n",
    "# save small object thumbnails as one image\n",
    "thumbnail_dir = os.path.join(output_path, \"object_thumbnails\")\n",
    "object_collage_path = os.path.join(output_path, \"object_collage.jpg\")\n",
    "collage(thumbnail_dir, object_collage_path)\n",
    "\n",
    "\n",
    "    "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Check mesh properties "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "import trimesh \n",
    "import os \n",
    "model_folder = \"../../data/google_scanned_object/models\"\n",
    "model_ids = os.listdir(model_folder)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Number of all meshes: 66\n",
      "Number of non-watertight meshes: 66\n",
      "Number of non-watertight meshes after filling holes: 66\n"
     ]
    }
   ],
   "source": [
    "# check list of non-watertight meshes in the folder\n",
    "print(\"Number of all meshes: {}\".format(len(model_ids)))\n",
    "\n",
    "non_watertight_meshes = []  \n",
    "for model_id in model_ids:\n",
    "    model_path = os.path.join(model_folder, model_id, \"meshes\", \"model.obj\")\n",
    "    mesh = trimesh.load(model_path)\n",
    "    if not mesh.is_watertight:\n",
    "        non_watertight_meshes.append(model_id)\n",
    "print(\"Number of non-watertight meshes: {}\".format(len(non_watertight_meshes)))\n",
    "\n",
    "# try to fix non-watertight meshes by filling holes\n",
    "fix_fail_meshes = []\n",
    "for model_id in non_watertight_meshes:\n",
    "    model_path = os.path.join(model_folder, model_id, \"meshes\", \"model.obj\")\n",
    "    mesh = trimesh.load(model_path)\n",
    "    mesh.fill_holes()\n",
    "    if not mesh.is_watertight:\n",
    "        fix_fail_meshes.append(model_id)\n",
    "print(\"Number of non-watertight meshes after filling holes: {}\".format(len(fix_fail_meshes)))\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████| 66/66 [00:03<00:00, 18.44it/s]\n"
     ]
    }
   ],
   "source": [
    "# Compute the volume of convex hull, bounding box, and their ratio for all meshes\n",
    "import tqdm \n",
    "\n",
    "volume_dict = {}\n",
    "for model_id in tqdm.tqdm(model_ids):\n",
    "    model_path = os.path.join(model_folder, model_id, \"meshes\", \"model.obj\")\n",
    "    mesh = trimesh.load(model_path)\n",
    "    volume_dict[model_id] = {\n",
    "        \"convex_hull_volume\": mesh.convex_hull.volume,\n",
    "        \"bbox_volume\": mesh.bounding_box.volume,\n",
    "        \"ratio\": mesh.convex_hull.volume/ mesh.bounding_box.volume\n",
    "    }"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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c3X99ddr5cqVeuedd1y+kI+JiVGrVq20aNEijRkzRkuXLlW3bt3UtGlTSc79cXGxVKtW7ZIv8K2svqtevXqy2Wz65JNPin0JdnFlAMqG6/ry47rePeW9rt+wYYOys7N11113lSuOdu3ayRijr776Si1btnSUl9SvS/87/t3Zzrt379Zzzz2n6667TmlpaZo5c6bGjRvnUowNGjRQr169lJycrJdeekmLFi3Sb37zG918882SfnlBvTvXGBcLDAxUdnZ2kXJP7fPCd5z5Ou7kqqImTpwoY4x+97vf6ezZs0WmF2bYJalbt26SVOSleWlpafr666/VvXv3MsXQqlUrderUSYsWLVJycrLy8vKKfN64b9++2r17t6666qpif425sDOcPHmyPvnkE7311ltasWKF/vWvf7n9q4+rmjRpoq+++sqpbP/+/RV6O2mhESNGKD8/XzNmzNAHH3yge++9V8HBwY7p3bt310cffeQ4ERZ64403FBwcXGLnI/3SjqysLKeXAJ89e1br1q2r0DbccMMNqlWrlvbu3VvsfoyOjvbIRQsAFNq5c6ckFXk04t1333X8UilJubm5eu+993TTTTfJz89PNWrUUKdOnfTuu+863blQUFCgpUuXqkGDBrr66qsl/fKPxiFDhqhr167avHmzbr/9do0YMcLlOyykX15OvHfvXv3hD3/Qjz/+6PSoT4sWLXTllVcqOTnZ6QXAJ0+e1DvvvOP44mJJKqvv6tu3r4wx+s9//lPs+d6du9sAlI7r+vLhut495b2uf+edd9S5c2ddeeWV5YqjsF+vX7++U/k///lPp22Qn5+vFStW6KqrrnIkdl3dzidPntRvf/tbNWnSRBs3btQjjzyiCRMm6PPPP3c5zhEjRuj48eN67rnntHPnTg0fPtzxOKg71xjFadKkifbv3++U3Dx27Jg2b97scnyu6N27t/z9/fXvf/+7xH3uS7iTq4rq0qWL5s6dq1GjRqljx456+OGH1aZNG507d047duzQvHnz1LZtW/Xr108tWrTQ73//e7366quOr04dPHhQzz77rBo2bKjHH3+8zHE88MADGjlypI4cOaKYmBi1aNHCafrzzz+vlJQUxcTE6LHHHlOLFi105swZHTx4UB988IFef/11NWjQQCkpKUpKStKzzz7r6JyTkpL05JNPKjY2tty/FFxs6NChGjJk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1k133HGHI5HFF68AAJ7UtGlTRUREKCUlxVF29uxZpaamKiYmpsT57Ha74weawgEAUPl4XBEA4DP69evnNP7CCy9o7ty52rp1q1q3bs0XrwAA5XbixAl9++23jvH09HTt3LlTderUUaNGjTR27FglJiaqefPmat68uRITExUcHKxBgwZ5MWoAgCtIcgEAfFJ+fr7+/ve/6+TJk+rSpUupX7y6VJKLFwIDAApt27ZNt9xyi2N83LhxkqT4+HgtXrxY48eP1+nTpzVq1CgdP35cnTp10vr16xUSEuKtkAEALiLJBQDwKbt27VKXLl105swZ1axZUytXrlTr1q0dn25394tXEi8EBgD8T2xsrIwxJU632WxKSEhQQkJC5QUFAKgQvJMLAOBTWrRooZ07d2rr1q16+OGHFR8fr7179zqmu/vFK4kXAgMAAABVAXdyAQB8SkBAgH7zm99IkqKjo5WWlqaXX35ZTz/9tKRfvngVGRnpqF/aF6+kXx5rtNvtngsaAAAAgNdxJxcAwKcZY5SXl1fmL14BAAAAqBq4kwsA4DOeeeYZxcXFqWHDhsrNzdXy5cu1adMmrV27VjabjS9eAQAAACgRSS4AgM/44YcfNHToUB09elRhYWFq166d1q5dq549e0oSX7wCAAAAUCK3HlecO3eu2rVrp9DQUIWGhqpLly768MMPHdONMUpISFBUVJSCgoIUGxurPXv2VHjQAIDL04IFC3Tw4EHl5eUpKytLGzZscCS4pP998ero0aM6c+aMUlNT1bZtWy9GDAAAAMBXuJXkatCggaZOnapt27Zp27Zt6tatm+644w5HImv69OmaOXOmZs+erbS0NEVERKhnz57Kzc31SPAAAAAAAACA5GaSq1+/frrtttt09dVX6+qrr9YLL7ygmjVrauvWrTLGaNasWZo0aZL69++vtm3basmSJTp16pSSk5M9FT8AAAAAAABQ9q8r5ufna/ny5Tp58qS6dOmi9PR0ZWZmqlevXo46drtdXbt21ebNm0tcTl5ennJycpwGAAAAAAAAwB1uJ7l27dqlmjVrym6366GHHtLKlSvVunVrZWZmSpLCw8Od6oeHhzumFScpKUlhYWGOoWHDhu6GBAAAAAAAgCrO7SRXixYttHPnTm3dulUPP/yw4uPjtXfvXsd0m83mVN8YU6TsQhMnTlR2drZjyMjIcDckAAAAAAAAVHH+7s4QEBCg3/zmN5Kk6OhopaWl6eWXX9bTTz8tScrMzFRkZKSjflZWVpG7uy5kt9tlt9vdDQMAAAAAAABwKPM7uQoZY5SXl6emTZsqIiJCKSkpjmlnz55VamqqYmJiyrsaAAAAAAAAoERu3cn1zDPPKC4uTg0bNlRubq6WL1+uTZs2ae3atbLZbBo7dqwSExPVvHlzNW/eXImJiQoODtagQYM8FT8AAAAAAADgXpLrhx9+0NChQ3X06FGFhYWpXbt2Wrt2rXr27ClJGj9+vE6fPq1Ro0bp+PHj6tSpk9avX6+QkBCPBA8AAAAAAABIbia5FixYcMnpNptNCQkJSkhIKE9MAAAAAAAAgFvK/U4uAAAAAAAAwNtIcgEAAAAAAMDy3HpcEQAAAACAy1GTCWu8tu6DU/t4bd3A5YQ7uQAAAAAAAGB5JLkAAAAAAABgeSS5AAAAAAAAYHkkuQAAAAAAAGB5JLkAAAAAAABgeSS5AAAAAAAAYHkkuQAAAAAAAGB5JLkAAAAAAABgeSS5AAAAAAAAYHkkuQAAAAAAAGB5JLkAAAAAAABgeSS5AAAAAAAAYHkkuQAAAAAAAGB5JLkAAAAAAABgeSS5AAAAAAAAYHkkuQAAAAAAAGB5JLkAAAAAAABgeSS5AAAAAAAAYHkkuQAAAAAAAGB5JLkAAAAA4Ffnz5/XH/7wBzVt2lRBQUFq1qyZnn/+eRUUFHg7NABAKfy9HQAAAAAA+Ipp06bp9ddf15IlS9SmTRtt27ZNw4cPV1hYmMaMGePt8AAAl0CSCwAAAAB+tWXLFt1xxx3q06ePJKlJkyZatmyZtm3b5uXIAACl4XFFAAAAAPjVjTfeqH/+85/av3+/JOlf//qXPv30U912221ejgwAUBru5AIAAACAXz399NPKzs5Wy5Yt5efnp/z8fL3wwgu67777SpwnLy9PeXl5jvGcnJzKCBUAcBGSXAAAAADwqxUrVmjp0qVKTk5WmzZttHPnTo0dO1ZRUVGKj48vdp6kpCRNmTKlkiMFKkaTCWu8HQJQYXhcEQAAAAB+9dRTT2nChAm69957dc0112jo0KF6/PHHlZSUVOI8EydOVHZ2tmPIyMioxIgBAIW4kwsAAAAAfnXq1ClVq+Z8L4Cfn58KCgpKnMdut8tut3s6NABAKUhyAQAAAMCv+vXrpxdeeEGNGjVSmzZttGPHDs2cOVMPPPCAt0MDAJSCJBcAAAAA/OrVV1/Vs88+q1GjRikrK0tRUVEaOXKknnvuOW+HBgAoBUkuAAAAAPhVSEiIZs2apVmzZnk7FACAm3jxPAAAAAAAACyPJBcAAAAAAAAsjyQXAAAAAAAALI8kFwAAAAAAACyPJBcAAAAAAAAsjyQXAAAAAAAALI8kFwAAAAAAACyPJBcAAAAAAAAsjyQXAAAAAAAALI8kFwAAAAAAACyPJBcAAAAAAAAsjyQXAAAAAAAALI8kFwAAAAAAACyPJBcAAAAAAAAsjyQXAAAAAAAALI8kFwAAAAAAACyPJBcAAAAAAAAsjyQXAAAAAAAALI8kFwAAAAAAACyPJBcAAAAAAAAsjyQXAAAAAAAALI8kFwAAAAAAACyPJBcAAAAAAAAsjyQXAAAAAAAALI8kFwAAAAAAACyPJBcAwGckJSXpuuuuU0hIiOrXr68777xT+/btc6pjjFFCQoKioqIUFBSk2NhY7dmzx0sRAwAAAPAVJLkAAD4jNTVVo0eP1tatW5WSkqLz58+rV69eOnnypKPO9OnTNXPmTM2ePVtpaWmKiIhQz549lZub68XIAQAAAHibv7cDAACg0Nq1a53GFy1apPr162v79u26+eabZYzRrFmzNGnSJPXv31+StGTJEoWHhys5OVkjR470RtgAAAAAfAB3cgEAfFZ2drYkqU6dOpKk9PR0ZWZmqlevXo46drtdXbt21ebNm70SIwAAAADfwJ1cAACfZIzRuHHjdOONN6pt27aSpMzMTElSeHi4U93w8HAdOnSoxGXl5eUpLy/PMZ6Tk+OBiAEAAAB4E3dyAQB80iOPPKKvvvpKy5YtKzLNZrM5jRtjipRdKCkpSWFhYY6hYcOGFR4vAAAAAO8iyQUA8DmPPvqoVq9erY0bN6pBgwaO8oiICEn/u6OrUFZWVpG7uy40ceJEZWdnO4aMjAzPBA4AAADAa9xKcvFpdwCAJxlj9Mgjj+jdd9/VRx99pKZNmzpNb9q0qSIiIpSSkuIoO3v2rFJTUxUTE1Picu12u0JDQ50GAAAAAJcXt5JcfNodAOBJo0eP1tKlS5WcnKyQkBBlZmYqMzNTp0+flvTLY4pjx45VYmKiVq5cqd27d2vYsGEKDg7WoEGDvBw9AAAAAG9y68XzfNodAOBJc+fOlSTFxsY6lS9atEjDhg2TJI0fP16nT5/WqFGjdPz4cXXq1Enr169XSEhIJUcLAAAAwJeU6+uK7n7anSQXAOBSjDGl1rHZbEpISFBCQoLnAwIAAABgGWVOclXUp935rDsAAAAAAADKq8xfV6yoT7vzWXcAAAAAAACUV5mSXBX5aXc+6w4AAADAl/znP//RkCFDVLduXQUHB6tDhw7avn27t8MCAJTCrSSXJz7tzmfdAQAAAPiK48eP64YbblD16tX14Ycfau/evXrppZdUq1Ytb4cGACiFW+/kGj16tJKTk/WPf/zD8Wl3SQoLC1NQUJDTp92bN2+u5s2bKzExkU+7AwAAALCEadOmqWHDhlq0aJGjrEmTJt4LCADgMrfu5Jo7d66ys7MVGxuryMhIx7BixQpHnfHjx2vs2LEaNWqUoqOj9Z///IdPuwMAAACwhNWrVys6Olq//e1vVb9+fV177bWaP3++t8MCALjArTu5+LQ7AAAAgMvZd999p7lz52rcuHF65pln9MUXX+ixxx6T3W7X/fffX+w8fDEeAHyDW0kuAAAAALicFRQUKDo6WomJiZKka6+9Vnv27NHcuXNLTHIlJSVpypQplRkmLjNNJqzxdgjAZaFMX1cEAAAAgMtRZGSkWrdu7VTWqlUrHT58uMR5+GI8APgG7uQCAAAAgF/dcMMN2rdvn1PZ/v371bhx4xLnsdvtstvtng4NAFAK7uQCAAAAgF89/vjj2rp1qxITE/Xtt98qOTlZ8+bN0+jRo70dGgCgFCS5AAAAAOBX1113nVauXKlly5apbdu2+uMf/6hZs2Zp8ODB3g4NAFAKHlcEAAAAgAv07dtXffv29XYYAAA3cScXAAAAAAAALI8kFwAAAAAAACyPJBcAAAAAAAAsjyQXAAAAAAAALI8kFwAAAAAAACyPJBcAAAAAAAAsjyQXAAAAAAAALI8kFwAAAAAAACyPJBcAAAAAAAAsjyQXAAAAAAAALI8kFwAAAAAAACyPJBcAAAAAAAAsjyQXAAAAAAAALI8kFwAAAAAAACyPJBcAAAAAAAAsjyQXAAAAAAAALI8kFwAAAAAAACyPJBcAAAAAAAAsjyQXAAAAAAAALI8kFwAAAAAAACyPJBcAAAAAAAAsjyQXAAAAAAAALI8kFwAAAAAAACyPJBcAAAAAAAAsjyQXAAAAAAAALI8kFwAAAAAAACyPJBcAAAAAAAAsjyQXAAAAAAAALI8kFwAAAAAAACyPJBcAAAAAAAAsjyQXAAAAAAAALI8kFwAAAAAAACyPJBcAAAAAAAAsjyQXAAAAAAAALI8kFwAAAAAAACyPJBcAAAAAAAAsjyQXAAAAAAAALI8kFwAAAAAAACyPJBcAAAAAlCApKUk2m01jx471digAgFKQ5AIAAACAYqSlpWnevHlq166dt0MBALiAJBcAAAAAXOTEiRMaPHiw5s+fr9q1a3s7HACAC0hyAQAAAMBFRo8erT59+qhHjx7eDgUA4CJ/bwcAAAAAAL5k+fLl+vLLL5WWluZS/by8POXl5TnGc3JyPBUaAOASuJMLAAAAAH6VkZGhMWPGaOnSpQoMDHRpnqSkJIWFhTmGhg0bejhKAEBxSHIBAAAAwK+2b9+urKwsdezYUf7+/vL391dqaqpeeeUV+fv7Kz8/v8g8EydOVHZ2tmPIyMjwQuQAAB5XBAAAAIBfde/eXbt27XIqGz58uFq2bKmnn35afn5+Reax2+2y2+2VFSIAoAQkuQAAAADgVyEhIWrbtq1TWY0aNVS3bt0i5QAA38LjigAAAAAAALA87uQCAAAAgEvYtGmTt0MAALiAO7kAAAAAAABgeSS5AAAAAAAAYHkkuQAAAAAAAGB5JLkAAAAAAABgeSS5AAAAAAAAYHkkuQAAAAAAAGB5JLkAAAAAAABgeSS5AAA+5eOPP1a/fv0UFRUlm82mVatWOU03xighIUFRUVEKCgpSbGys9uzZ451gAQAAAPgMklwAAJ9y8uRJtW/fXrNnzy52+vTp0zVz5kzNnj1baWlpioiIUM+ePZWbm1vJkQIAAADwJf7eDgAAgAvFxcUpLi6u2GnGGM2aNUuTJk1S//79JUlLlixReHi4kpOTNXLkyMoMFQAAAIAPcftOLh4jAQB4S3p6ujIzM9WrVy9Hmd1uV9euXbV582YvRgYAAADA29xOcvEYCQDAWzIzMyVJ4eHhTuXh4eGOacXJy8tTTk6O0wAAAADg8uL244o8RgIA8DabzeY0bowpUnahpKQkTZkyxdNhVYomE9Z4bd0Hp/bx2roBAACA0lToi+d5jAQA4EkRERGSVOSuraysrCJ3d11o4sSJys7OdgwZGRkejRMAAABA5avQJFdZHiPhERIAgKuaNm2qiIgIpaSkOMrOnj2r1NRUxcTElDif3W5XaGio0wAAAADg8uKRryu68xjJ5fQICQCg/E6cOKFvv/3WMZ6enq6dO3eqTp06atSokcaOHavExEQ1b95czZs3V2JiooKDgzVo0CAvRg0AAADA2yo0yXXhYySRkZGO8ks9RjJx4kSNGzfOMZ6Tk6OGDRtWZFgAAAvZtm2bbrnlFsd4YR8RHx+vxYsXa/z48Tp9+rRGjRql48ePq1OnTlq/fr1CQkK8FTIAAAAAH1ChSa4LHyO59tprJf3vMZJp06YVO4/dbpfdbq/IMAAAFhYbGytjTInTbTabEhISlJCQUHlBAQAAAPB5bie5eIwEAAAAAC5f3vySLwCUh9tJLh4jAQAAAAAAgK9xO8nFYyQAAAAAAADwNdW8HQAAAAAAAABQXiS5AAAAAAAAYHkkuQAAAAAAAGB5JLkAAAAAAABgeSS5AAAAAAAAYHkkuQAAAAAAAGB5JLkAAAAAAABgeSS5AAAAAAAAYHkkuQAAAAAAAGB5/t4O4HLTZMIar6374NQ+Xls3AAAAAACAN3EnFwAAAAAAACyPJBcAAAAAAAAsjyQXAAAAAAAALI8kFwAAAAAAACyPJBcAAAAAAAAsjyQXAAAAAAAALI8kFwAAAAAAACyPJBcAAAAA/CopKUnXXXedQkJCVL9+fd15553at2+ft8MCALiAJBcAAAAA/Co1NVWjR4/W1q1blZKSovPnz6tXr146efKkt0MDAJTC39sBAAAAAICvWLt2rdP4okWLVL9+fW3fvl0333yzl6ICALiCJBcAAAAAlCA7O1uSVKdOnRLr5OXlKS8vzzGek5Pj8bgAAEWR5AIAAACAYhhjNG7cON14441q27ZtifWSkpI0ZcqUSowMgJU1mbDG2yFctngnFwAAAAAU45FHHtFXX32lZcuWXbLexIkTlZ2d7RgyMjIqKUIAwIW4kwsAAAAALvLoo49q9erV+vjjj9WgQYNL1rXb7bLb7ZUUGQCgJCS5AAAAAOBXxhg9+uijWrlypTZt2qSmTZt6OyQAgItIcgEAAADAr0aPHq3k5GT94x//UEhIiDIzMyVJYWFhCgoK8nJ0AIBL4Z1cAAAAAPCruXPnKjs7W7GxsYqMjHQMK1as8HZoAIBScCcXAAAAAPzKGOPtEAAAZcSdXAAAAAAAALA8klwAAAAAAACwPJJcAAAAAAAAsDySXAAAAAAAALA8klwAAAAAAACwPJJcAAAAAAAAsDySXAAAAAAAALA8klwAAAAAAACwPJJcAAAAAAAAsDySXAAAAAAAALA8f28HAAAArKHJhDVeXf/BqX28un4AAAD4Nu7kAgAAAAAAgOVxJxcqhDd/3eeXfQAAAAAAwJ1cAAAAAAAAsDySXAAAAAAAALA8klwAAAAAAACwPJJcAAAAAAAAsDySXAAAAAAAALA8vq4IAAAAAD7Gm18vB6oC/sYuTyS5LiP8kQIAAAAAgKqKxxUBAAAAAABgeSS5AAAAAAAAYHkkuQAAAAAAAGB5JLkAAAAAAABgeSS5AAAAAAAAYHkkuQAAAAAAAGB5/t4OAAAAwNc1mbDGa+s+OLWP19YNAABgJdzJBQAAAAAAAMsjyQUAAAAAAADLI8kFAAAAAAAAyyPJBQAAAAAAAMsjyQUAAAAAAADLI8kFAAAAAAAAyyPJBQAAAAAAAMvz93YAAAAAKFmTCWu8HYJXHJzax2vrZpsDAGBNJLlged68EOVi0Dv4xwcAAAAA4GI8rggAAAAAAADLI8kFAAAAAAAAy/NYkmvOnDlq2rSpAgMD1bFjR33yySeeWhUAoAqinwEAeBL9DABYj0eSXCtWrNDYsWM1adIk7dixQzfddJPi4uJ0+PBhT6wOAFDF0M8AADyJfgYArMkjSa6ZM2dqxIgRevDBB9WqVSvNmjVLDRs21Ny5cz2xOgBAFUM/AwDwJPoZALCmCv+64tmzZ7V9+3ZNmDDBqbxXr17avHlzkfp5eXnKy8tzjGdnZ0uScnJyyhxDQd6pMs8LuKM8xynKrqr+jZf1eCuczxhTkeF4jbv9jFTxfU1VPQa9zZvnXPZ55WN/V77ybPPLqa/xhX5GqrrHIYDLV2X0MxWe5Prpp5+Un5+v8PBwp/Lw8HBlZmYWqZ+UlKQpU6YUKW/YsGFFhwZUuLBZ3o4AVUl5j7fc3FyFhYVVSCze5G4/I9HXXC4451Yt7O/KVxHb/HLoa+hnAMAzKqOfqfAkVyGbzeY0bowpUiZJEydO1Lhx4xzjBQUF+u9//6u6desWW780OTk5atiwoTIyMhQaGup+4F5k5dgla8dv5dgla8dv5dgla8RvjFFubq6ioqK8HUqFcrWfkSq2r7HCPveEqtpuqeq2nXZXrXZL5Wv75djXeKufqWiX2zFNe3wb7fFtVm6Pq/1MhSe56tWrJz8/vyK/cmRlZRX5NUSS7Ha77Ha7U1mtWrXKHUdoaKjldlohK8cuWTt+K8cuWTt+K8cu+X78Vv9V/ULu9jOSZ/oaX9/nnlJV2y1V3bbT7qqnrG2/XPoaX+lnKtrldkzTHt9Ge3ybVdvjSj9T4S+eDwgIUMeOHZWSkuJUnpKSopiYmIpeHQCgiqGfAQB4Ev0MAFiXRx5XHDdunIYOHaro6Gh16dJF8+bN0+HDh/XQQw95YnUAgCqGfgYA4En0MwBgTR5Jcg0cOFDHjh3T888/r6NHj6pt27b64IMP1LhxY0+szondbtfkyZOL3C5sBVaOXbJ2/FaOXbJ2/FaOXbJ+/FZFP1P5qmq7parbdtpdtdotVe22X8yb/UxFu9z2K+3xbbTHt11u7SmOzVwO3/kFAAAAAABAlVbh7+QCAAAAAAAAKhtJLgAAAAAAAFgeSS4AAAAAAABYHkkuAAAAAAAAWJ5Xk1xz5sxR06ZNFRgYqI4dO+qTTz65ZP3U1FR17NhRgYGBatasmV5//fUidd555x21bt1adrtdrVu31sqVK91erzFGCQkJioqKUlBQkGJjY7Vnzx6fiD8pKUnXXXedQkJCVL9+fd15553at2+fU51hw4bJZrM5DZ07d/Z67AkJCUXiioiIcKrjy9u+SZMmReK32WwaPXq0o443tv2ePXs0YMAAR3yzZs0qdjm+ety7Er+vHveuxF6Rxz0qhq/2PZ7mq+f9yuCr511P89VznqdVdLvnz5+vm266SbVr11bt2rXVo0cPffHFF+Veryd4o+2+sM9R9uPvs88+k7+/vzp06ODZAN3kTns2bdpU7DX6N998U4kRX5q7+ycvL0+TJk1S48aNZbfbddVVV2nhwoWVFG3p3GlPcdfoNptNbdq0qcSIL83d/fPWW2+pffv2Cg4OVmRkpIYPH65jx45VUrSlc7c9r732mlq1aqWgoCC1aNFCb7zxRiVF6iHGS5YvX26qV69u5s+fb/bu3WvGjBljatSoYQ4dOlRs/e+++84EBwebMWPGmL1795r58+eb6tWrm7fffttRZ/PmzcbPz88kJiaar7/+2iQmJhp/f3+zdetWt9Y7depUExISYt555x2za9cuM3DgQBMZGWlycnK8Hn/v3r3NokWLzO7du83OnTtNnz59TKNGjcyJEyccdeLj482tt95qjh496hiOHTvm9dgnT55s2rRp4xRXVlaW07p8edtnZWU5xZ6SkmIkmY0bN3p123/xxRfmySefNMuWLTMRERHmz3/+c5Hl+PJx70r8vnrcuxJ7RR33qBi+3Pd4ki+f9z3Nl8+7nuTL5zxP8kS7Bw0aZF577TWzY8cO8/XXX5vhw4ebsLAw8/3335d5vZ7grbZ7e5+j7Mffzz//bJo1a2Z69epl2rdvXznBusDd9mzcuNFIMvv27XM6Ds+fP1/JkRevLPvn9ttvN506dTIpKSkmPT3dfP755+azzz6rxKhL5m57fv75Z6f9kpGRYerUqWMmT55cuYGXwN32fPLJJ6ZatWrm5ZdfNt9995355JNPTJs2bcydd95ZyZEXz932zJkzx4SEhJjly5ebf//732bZsmWmZs2aZvXq1ZUcecXxWpLr+uuvNw899JBTWcuWLc2ECROKrT9+/HjTsmVLp7KRI0eazp07O8bvuecec+uttzrV6d27t7n33ntdXm9BQYGJiIgwU6dOdUw/c+aMCQsLM6+//rrX479YVlaWkWRSU1MdZfHx8eaOO+4ocR5vxT558uRLdqBW2/ZjxowxV111lSkoKHCUeWPbX6hx48bF/qPDl497V+K/mK8c967EXlHHPSqGr/Y9nuar5/3K4KvnXU/z1XOep3m63cYYc/78eRMSEmKWLFlS5vV6grfa7u19jrIffwMHDjR/+MMffG4futuewiTX8ePHKyE697nbng8//NCEhYU5/VjrS8p7vlu5cqWx2Wzm4MGDngjPbe62Z8aMGaZZs2ZOZa+88opp0KCBx2J0h7vt6dKli3nyySedysaMGWNuuOEGj8XoaV55XPHs2bPavn27evXq5VTeq1cvbd68udh5tmzZUqR+7969tW3bNp07d+6SdQqX6cp609PTlZmZ6VTHbrera9eubi3HE/EXJzs7W5JUp04dp/JNmzapfv36uvrqq/W73/1OWVlZPhH7gQMHFBUVpaZNm+ree+/Vd99955hmpW1/9uxZLV26VA888IBsNpvTtMre9qXx9eO+LHzluHdVeY97VAxf7ns8ydvnzUsd/57my+ddT/Llc54nVVa7T506pXPnzjn6IG/v77LGUBFtL+TNv/OqrqzH36JFi/Tvf/9bkydP9nSIbinP39O1116ryMhIde/eXRs3bvRkmC4rS3tWr16t6OhoTZ8+XVdeeaWuvvpqPfnkkzp9+nRlhHxJFXG+W7BggXr06KHGjRt7IkS3lKU9MTEx+v777/XBBx/IGKMffvhBb7/9tvr06VMZIV9SWdqTl5enwMBAp7KgoCB98cUX5fr3mjd5Jcn1008/KT8/X+Hh4U7l4eHhyszMLHaezMzMYuufP39eP/300yXrFC7TlfUW/re8y/FE/BczxmjcuHG68cYb1bZtW0d5XFyc3nrrLX300Ud66aWXlJaWpm7duikvL8+rsXfq1ElvvPGG1q1bp/nz5yszM1MxMTGO55ettO1XrVqln3/+WcOGDXMq98a2L42vH/fu8qXj3hUVcdyjYvhy3+NJvnze9zRfPu96ki+f8zypsto9YcIEXXnllerRo0eZ11vRvNV2yft/51VdWfb9gQMHNGHCBL311lvy9/evjDBdVpb2REZGat68eXrnnXf07rvvqkWLFurevbs+/vjjygj5ksrSnu+++06ffvqpdu/erZUrV2rWrFl6++23nd4D7C3lPd8dPXpUH374oR588EFPheiWsrQnJiZGb731lgYOHKiAgABFRESoVq1aevXVVysj5EsqS3t69+6tv/71r9q+fbuMMdq2bZsWLlyoc+fOlfnfa97m1bPaxXfAGGOKlJVW/+JyV5ZZmXU8EX+hRx55RF999ZU+/fRTp/KBAwc6/r9t27aKjo5W48aNtWbNGseLuL0Re1xcnOP/r7nmGnXp0kVXXXWVlixZonHjxrm8HG/Ff6EFCxYoLi5OUVFRTuXe2vau8OXj3h2+dtyXpiKPe1QMX+57PMmXz/ue5svnXU/y5XOeJ3my3dOnT9eyZcu0adOmIr98e3t/lyWGimi7L+xzuL7v8/PzNWjQIE2ZMkVXX311ZYXnNneO5RYtWqhFixaO8S5duigjI0Mvvviibr75Zo/G6Sp32lNQUCCbzaa33npLYWFhkqSZM2fq7rvv1muvvaagoCCPx1uasp7vFi9erFq1aunOO+/0UGRl40579u7dq8cee0zPPfecevfuraNHj+qpp57SQw89pAULFlRGuKVypz3PPvusMjMz1blzZxljFB4ermHDhmn69Ony8/OrjHArnFfu5KpXr578/PyKZBOzsrKKZB0LRUREFFvf399fdevWvWSdwmW6st7Cr8GUdzmeiP9Cjz76qFavXq2NGzeqQYMGxa6zUGRkpBo3bqwDBw74ROyFatSooWuuuUYHDhxwLEPy/W1/6NAhbdiwwaVfICpj25fG1497d/jacV8WZTnuUTF8ue/xJF84bxa6+Pj3NF8+73qSL5/zPMnT7X7xxReVmJio9evXq127duVab0XzVtuLU9l/51Wdu/s+NzdX27Zt0yOPPCJ/f3/5+/vr+eef17/+9S/5+/vro48+qqzQi1VRf0+dO3f2iWOwLO2JjIzUlVde6UhwSVKrVq1kjNH333/v0XhLU579Y4zRwoULNXToUAUEBHgyTJeVpT1JSUm64YYb9NRTT6ldu3bq3bu35syZo4ULF+ro0aOVEXaJytKeoKAgLVy4UKdOndLBgwd1+PBhNWnSRCEhIapXr15lhF3hvJLkCggIUMeOHZWSkuJUnpKSopiYmGLn6dKlS5H669evV3R0tKpXr37JOoXLdGW9TZs2VUREhFOds2fPKjU11a3leCJ+6ZeTwyOPPKJ3331XH330kZo2bVrs+i507NgxZWRkKDIy0quxXywvL09ff/21IiMjJfn+ti+0aNEi1a9f36Xnritj25fG1497V/jqcV8WZTnuUTF8ue/xJF84bxa6+Pj3NF8+73qSL5/zPMmT7Z4xY4b++Mc/au3atYqOji73eiuat9penMr+O6/q3N33oaGh2rVrl3bu3OkYHnroIbVo0UI7d+5Up06dKiv0YlXU39OOHTt84hgsS3tuuOEGHTlyRCdOnHCU7d+/X9WqVSv1R15PK8/+SU1N1bfffqsRI0Z4MkS3lKU9p06dUrVqzmmUwjueCu+G9Zby7J/q1aurQYMG8vPz0/Lly9W3b98i7bSMCnuFvZsKP225YMECs3fvXjN27FhTo0YNx1cWJkyYYIYOHeqoX/iZ48cff9zs3bvXLFiwoMhnjj/77DPj5+dnpk6dar7++mszderUEj/jXtJ6jTFm6tSpJiwszLz77rtm165d5r777jORkZEmJyfH6/E//PDDJiwszGzatMnpU6ynTp0yxhiTm5trnnjiCbN582aTnp5uNm7caLp06WKuvPJKR/zeiv2JJ54wmzZtMt99953ZunWr6du3rwkJCbHMtjfGmPz8fNOoUSPz9NNPm4t5a9vn5eWZHTt2mB07dpjIyEjz5JNPmh07dpgDBw64vM28ue1did9Xj3tXYq+o4x4Vw5f7nsux3a4c/1Zse0Wddy/Hdnt7n3ui3dOmTTMBAQHm7bffduqDcnNzXV7v5dx2b+9zuL/vL+ZrX1d0tz1//vOfzcqVK83+/fvN7t27zYQJE4wk884773irCU7cbU9ubq5p0KCBufvuu82ePXtMamqqad68uXnwwQe91QQnZT3ehgwZYjp16lTZ4ZbK3fYsWrTI+Pv7mzlz5ph///vf5tNPPzXR0dHm+uuv91YTnLjbnn379pk333zT7N+/33z++edm4MCBpk6dOiY9Pd1LLSg/ryW5jDHmtddeM40bNzYBAQHm//7v/0xqaqpjWnx8vOnatatT/U2bNplrr73WBAQEmCZNmpi5c+cWWebf//5306JFC1O9enXTsmXLYk9ul1qvMcYUFBSYyZMnm4iICGO3283NN99sdu3a5RPxSyp2WLRokTHGmFOnTplevXqZK664wlSvXt00atTIxMfHm8OHD3s99oEDB5rIyEhTvXp1ExUVZfr372/27NnjVMeXt70xxqxbt85IMvv27SsyzVvbPj09vdhj4uLl+Opx70r8vnrcuxJ7RR73qBi+2vd4mq+e9yuDr553Pc1Xz3meVtHtbty4cbHtnjx5ssvrrSzeaLsv7HO4v+8v5GtJLmPca8+0adPMVVddZQIDA03t2rXNjTfeaNasWeOFqEvm7v75+uuvTY8ePUxQUJBp0KCBGTdunOPHXV/gbnt+/vlnExQUZObNm1fJkbrG3fa88sorpnXr1iYoKMhERkaawYMHm++//76Soy6ZO+3Zu3ev6dChgwkKCjKhoaHmjjvuMN98840Xoq44NmO8fE8dAAAAAAAAUE4WfcgSAAAAAAAA+B+SXAAAAAAAALA8klwAAAAAAACwPJJcAAAAAAAAsDySXAAAAAAAALA8klwAAAAAAACwPJJcAAAAAAAAsDySXAAAAAAAALA8klwAAAAAAACwPJJcAAAAAAAAsDySXAAAAAAAALA8klwAAAAAAACwvP8H+KGUG8fB92YAAAAASUVORK5CYII=",
      "text/plain": [
       "<Figure size 1500x500 with 3 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# visualze the distribution of convex hull volume, voxel volume, and their ratio\n",
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "\n",
    "convex_hull_volume = [volume_dict[model_id][\"convex_hull_volume\"] for model_id in volume_dict.keys()]\n",
    "bbox_volume = [volume_dict[model_id][\"bbox_volume\"] for model_id in volume_dict.keys()]\n",
    "ratio = [volume_dict[model_id][\"ratio\"] for model_id in volume_dict.keys()]\n",
    "\n",
    "# use subplot to plot three figures in one figure\n",
    "fig, axs = plt.subplots(1, 3, figsize=(15, 5))\n",
    "axs[0].hist(convex_hull_volume, bins=10)\n",
    "axs[0].set_title(\"Convex Hull Volume\")\n",
    "axs[1].hist(bbox_volume, bins=10)\n",
    "axs[1].set_title(\"Bbox Volume\")\n",
    "axs[2].hist(ratio, bins=10)\n",
    "axs[2].set_title(\"Convex Hull Volume / Bbox Volume\")\n",
    "plt.show()\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Annotate model names "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "object_ids = [ file.split(\".\")[0] for file in\n",
    "    os.listdir(\"../../data/google_scanned_object/object_thumbnails\")\n",
    "]\n",
    "container_ids = [ file.split(\".\")[0] for file in\n",
    "    os.listdir(\"../../data/google_scanned_object/container_thumbnails\")\n",
    "]\n",
    "\n",
    "model_ids = object_ids + container_ids\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "# generate json file with model_ids as keys and empty string as values\n",
    "import json \n",
    "# with open(\"../../data/google_scanned_object/model_name_manual.json\", 'w') as f:\n",
    "#     json.dump({model_id: \"\" for model_id in model_ids}, f, indent=4)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "housekeep",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.17"
  },
  "orig_nbformat": 4
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
